getTeachers() {
54 | return mTeachers;
55 | }
56 |
57 | public String getSchedule() {
58 | return mSchedule;
59 | }
60 |
61 | public String getClassroom() {
62 | return mClassroom;
63 | }
64 |
65 | public int getVacancy() {
66 | return mVacancy;
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/model/SubjectModel.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.model;
2 |
3 | /**
4 | * Class that represents a SubjectModel in the domain layer.
5 | */
6 | public class SubjectModel {
7 |
8 | private String mName;
9 | private Integer mCode;
10 |
11 | private SubjectModel() {}
12 |
13 | public static SubjectModel buildSubjectModel(){
14 | return new SubjectModel();
15 | }
16 |
17 | public SubjectModel addName(String name) {
18 | mName = name;
19 | return this;
20 | }
21 |
22 | public SubjectModel addCode(int code) {
23 | mCode = code;
24 | return this;
25 | }
26 |
27 | public Integer getCode() {
28 | return mCode;
29 | }
30 |
31 | public String getName() {
32 | return mName;
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/AbstractPresenter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters;
2 |
3 |
4 | import com.clean.domain.executor.Executor;
5 | import com.clean.domain.executor.MainThread;
6 |
7 | /**
8 | * This is a base class for all presenters which are communicating with interactors. This base class will hold a
9 | * reference to the Executor and MainThread objects that are needed for running interactors in a background thread.
10 | */
11 | public abstract class AbstractPresenter {
12 | protected Executor mExecutor;
13 | protected MainThread mMainThread;
14 |
15 | public AbstractPresenter(Executor executor, MainThread mainThread) {
16 | mExecutor = executor;
17 | mMainThread = mainThread;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/BasePresenter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters;
2 |
3 | public interface BasePresenter {
4 | /**
5 | * Method that control the lifecycle of the view. It should be called in the view's
6 | * (Activity or Fragment) onResume() method.
7 | */
8 | void resume();
9 |
10 | /**
11 | * Method that controls the lifecycle of the view. It should be called in the view's
12 | * (Activity or Fragment) onPause() method.
13 | */
14 | void pause();
15 |
16 | /**
17 | * Method that controls the lifecycle of the view. It should be called in the view's
18 | * (Activity or Fragment) onStop() method.
19 | */
20 | void stop();
21 |
22 | /**
23 | * Method that control the lifecycle of the view. It should be called in the view's
24 | * (Activity or Fragment) onDestroy() method.
25 | */
26 | void destroy();
27 |
28 |
29 | /**
30 | * Method that should signal the appropriate view to show the appropriate error with the provided message.
31 | */
32 | void onError(String message);
33 | }
34 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/courses/CoursesPresenter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters.courses;
2 |
3 | import com.clean.presentation.presenters.BasePresenter;
4 | import com.clean.presentation.ui.BaseView;
5 |
6 | import java.util.List;
7 |
8 |
9 | public interface CoursesPresenter extends BasePresenter {
10 |
11 | interface View extends BaseView {
12 | void displayCourses(List courses);
13 | // TODO: Add your view methods
14 | }
15 |
16 | // TODO: Add your presenter methods
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/courses/CoursesPresenterImpl.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters.courses;
2 |
3 | import com.clean.domain.executor.Executor;
4 | import com.clean.domain.executor.MainThread;
5 | import com.clean.domain.interactors.show_courses.ShowCourses;
6 | import com.clean.domain.interactors.show_courses.ShowCoursesImpl;
7 | import com.clean.domain.repository.StudentRepository;
8 | import com.clean.presentation.presenters.AbstractPresenter;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Created by dmilicic on 12/13/15.
14 | */
15 | public class CoursesPresenterImpl extends AbstractPresenter implements CoursesPresenter,
16 | ShowCourses.Callback {
17 |
18 | private View mView;
19 | private StudentRepository mRepository;
20 | private int mSubjectCode;
21 |
22 | /**********************************************************************************************/
23 | /**********************************************************************************************/
24 |
25 | public CoursesPresenterImpl(Executor executor,
26 | MainThread mainThread,
27 | View view,
28 | StudentRepository repository,
29 | int subjectCode) {
30 | super(executor, mainThread);
31 | mView = view;
32 | mRepository = repository;
33 | mSubjectCode = subjectCode;
34 | }
35 |
36 | /**********************************************************************************************/
37 | /**********************************************************************************************/
38 |
39 | @Override
40 | public void resume() {
41 | mView.showProgress();
42 |
43 | // initialize the interactor
44 | ShowCourses interactor = new ShowCoursesImpl(
45 | mExecutor,
46 | mMainThread,
47 | this,
48 | mRepository
49 | );
50 |
51 | interactor.setSubjectCode(mSubjectCode);
52 | // run the interactor
53 | interactor.execute();
54 | }
55 |
56 | /**********************************************************************************************/
57 | /**********************************************************************************************/
58 |
59 | @Override
60 | public void pause() {
61 |
62 | }
63 |
64 | /**********************************************************************************************/
65 | /**********************************************************************************************/
66 |
67 | @Override
68 | public void stop() {
69 |
70 | }
71 |
72 | /**********************************************************************************************/
73 | /**********************************************************************************************/
74 |
75 | @Override
76 | public void destroy() {
77 |
78 | }
79 |
80 | /**********************************************************************************************/
81 | /**********************************************************************************************/
82 |
83 | @Override
84 | public void onError(String message) {
85 |
86 | }
87 |
88 | /**********************************************************************************************/
89 | /**********************************************************************************************/
90 |
91 | @Override
92 | public void onCoursesRetrieved(List courses) {
93 | mView.displayCourses(courses);
94 | }
95 |
96 | /**********************************************************************************************/
97 | /**********************************************************************************************/
98 |
99 | @Override
100 | public void onRetrievalFailed(String error) {
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/enroll_to_course/EnrollToCoursePresenter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters.enroll_to_course;
2 |
3 | import com.clean.presentation.presenters.BasePresenter;
4 | import com.clean.presentation.ui.BaseView;
5 |
6 |
7 | public interface EnrollToCoursePresenter extends BasePresenter {
8 |
9 | interface View extends BaseView {
10 | void notifyAlreadyEnrolledSubject();
11 | void notifyEnrolledInSevenCourses();
12 | void notifyEnrolled();
13 | // TODO: Add your view methods
14 | }
15 |
16 | // TODO: Add your presenter methods
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/enrolled_courses/EnrolledCoursesPresenter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters.enrolled_courses;
2 |
3 | import com.clean.presentation.presenters.BasePresenter;
4 | import com.clean.presentation.ui.BaseView;
5 |
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 |
10 | public interface EnrolledCoursesPresenter extends BasePresenter {
11 |
12 | interface View extends BaseView {
13 | void displayCourses(List courses);
14 | // TODO: Add your view methods
15 | }
16 |
17 | // TODO: Add your presenter methods
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/enrolled_courses/EnrolledCoursesPresenterImpl.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters.enrolled_courses;
2 |
3 | import com.clean.domain.executor.Executor;
4 | import com.clean.domain.executor.MainThread;
5 | import com.clean.domain.interactors.show_enrolled_courses.ShowEnrolledCourses;
6 | import com.clean.domain.interactors.show_enrolled_courses.ShowEnrolledCoursesImpl;
7 | import com.clean.domain.repository.StudentRepository;
8 | import com.clean.presentation.presenters.AbstractPresenter;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Created by dmilicic on 12/13/15.
14 | */
15 | public class EnrolledCoursesPresenterImpl extends AbstractPresenter implements EnrolledCoursesPresenter,
16 | ShowEnrolledCourses.Callback {
17 |
18 | private View mView;
19 | private StudentRepository mRepository;
20 |
21 | /**********************************************************************************************/
22 | /**********************************************************************************************/
23 |
24 | public EnrolledCoursesPresenterImpl(Executor executor,
25 | MainThread mainThread,
26 | View view,
27 | StudentRepository repository) {
28 | super(executor, mainThread);
29 | mView = view;
30 | mRepository = repository;
31 | }
32 |
33 | /**********************************************************************************************/
34 | /**********************************************************************************************/
35 |
36 | @Override
37 | public void resume() {
38 | mView.showProgress();
39 |
40 | // initialize the interactor
41 | ShowEnrolledCourses interactor = new ShowEnrolledCoursesImpl(
42 | mExecutor,
43 | mMainThread,
44 | this,
45 | mRepository
46 | );
47 |
48 | // run the interactor
49 | interactor.execute();
50 | }
51 |
52 | /**********************************************************************************************/
53 | /**********************************************************************************************/
54 |
55 | @Override
56 | public void pause() {
57 |
58 | }
59 |
60 | /**********************************************************************************************/
61 | /**********************************************************************************************/
62 |
63 | @Override
64 | public void stop() {
65 |
66 | }
67 |
68 | /**********************************************************************************************/
69 | /**********************************************************************************************/
70 |
71 | @Override
72 | public void destroy() {
73 |
74 | }
75 |
76 | /**********************************************************************************************/
77 | /**********************************************************************************************/
78 |
79 | @Override
80 | public void onError(String message) {
81 |
82 | }
83 |
84 | /**********************************************************************************************/
85 | /**********************************************************************************************/
86 |
87 | @Override
88 | public void onCoursesRetrieved(List courses) {
89 | mView.displayCourses(courses);
90 | }
91 |
92 | /**********************************************************************************************/
93 | /**********************************************************************************************/
94 |
95 | @Override
96 | public void onRetrievalFailed(String error) {
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/main/MainPresenter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters.main;
2 |
3 | import com.clean.presentation.presenters.BasePresenter;
4 | import com.clean.presentation.ui.BaseView;
5 |
6 | import java.util.List;
7 |
8 |
9 | public interface MainPresenter extends BasePresenter {
10 |
11 | interface View extends BaseView {
12 | void displaySubjects(List subjects);
13 | // TODO: Add your view methods
14 | }
15 |
16 | // TODO: Add your presenter methods
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/presenters/main/MainPresenterImpl.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.presenters.main;
2 |
3 | import com.clean.domain.executor.Executor;
4 | import com.clean.domain.executor.MainThread;
5 | import com.clean.domain.interactors.show_available_subjects.ShowAvailableSubjects;
6 | import com.clean.domain.interactors.show_available_subjects.ShowAvailableSubjectsImpl;
7 | import com.clean.domain.repository.StudentRepository;
8 | import com.clean.presentation.presenters.AbstractPresenter;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Created by dmilicic on 12/13/15.
14 | */
15 | public class MainPresenterImpl extends AbstractPresenter implements MainPresenter,
16 | ShowAvailableSubjects.Callback {
17 |
18 | private MainPresenter.View mView;
19 | private StudentRepository mRepository;
20 |
21 | /**********************************************************************************************/
22 | /**********************************************************************************************/
23 |
24 | public MainPresenterImpl(Executor executor,
25 | MainThread mainThread,
26 | View view,
27 | StudentRepository repository) {
28 | super(executor, mainThread);
29 | mView = view;
30 | mRepository = repository;
31 | }
32 |
33 | /**********************************************************************************************/
34 | /**********************************************************************************************/
35 |
36 | @Override
37 | public void resume() {
38 | mView.showProgress();
39 |
40 | // initialize the interactor
41 | ShowAvailableSubjects interactor = new ShowAvailableSubjectsImpl(
42 | mExecutor,
43 | mMainThread,
44 | this,
45 | mRepository
46 | );
47 |
48 | // run the interactor
49 | interactor.execute();
50 | }
51 |
52 | /**********************************************************************************************/
53 | /**********************************************************************************************/
54 |
55 | @Override
56 | public void pause() {
57 |
58 | }
59 |
60 | /**********************************************************************************************/
61 | /**********************************************************************************************/
62 |
63 | @Override
64 | public void stop() {
65 |
66 | }
67 |
68 | /**********************************************************************************************/
69 | /**********************************************************************************************/
70 |
71 | @Override
72 | public void destroy() {
73 |
74 | }
75 |
76 | /**********************************************************************************************/
77 | /**********************************************************************************************/
78 |
79 | @Override
80 | public void onError(String message) {
81 |
82 | }
83 |
84 | /**********************************************************************************************/
85 | /**********************************************************************************************/
86 |
87 | @Override
88 | public void onSubjectsRetrieved(List subjects) {
89 | mView.displaySubjects(subjects);
90 | }
91 |
92 | /**********************************************************************************************/
93 | /**********************************************************************************************/
94 |
95 | @Override
96 | public void onRetrievalFailed(String error) {
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/BaseView.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui;
2 |
3 | /**
4 | *
5 | * This interface represents a basic view. All views should implement these common methods.
6 | *
7 | */
8 | public interface BaseView {
9 |
10 | /**
11 | * This is a general method used for showing some kind of progress during a background task. For example, this
12 | * method should show a progress bar and/or disable buttons before some background work starts.
13 | */
14 | void showProgress();
15 |
16 | /**
17 | * This is a general method used for hiding progress information after a background task finishes.
18 | */
19 | void hideProgress();
20 |
21 | /**
22 | * This method is used for showing error messages on the UI.
23 | *
24 | * @param message The error message to be displayed.
25 | */
26 | void showError(String message);
27 | }
28 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/activities/CoursesActivity.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.activities;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.util.Log;
8 | import android.widget.Toast;
9 |
10 | import com.clean.R;
11 | import com.clean.presentation.UniquePointOfInstanciation;
12 | import com.clean.presentation.mapper.CourseModelMapper;
13 | import com.clean.presentation.model.CourseModel;
14 | import com.clean.presentation.presenters.BasePresenter;
15 | import com.clean.presentation.presenters.courses.CoursesPresenter;
16 | import com.clean.presentation.ui.adapters.CoursesNamesRecyclerAdapter;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import butterknife.ButterKnife;
22 |
23 | public class CoursesActivity extends AppCompatActivity implements CoursesPresenter.View {
24 |
25 | public static final String SUBJECT_CODE = "code";
26 | public static final String SUBJECT_NAME = "name";
27 | private BasePresenter mPresenter;
28 | private RecyclerView mCoursesView;
29 | private List mCourses;
30 | private int mSubjectCode;
31 |
32 | /**********************************************************************************************/
33 | /**********************************************************************************************/
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_courses);
39 | ButterKnife.bind(this);
40 | getSupportActionBar().setTitle(getIntent().getStringExtra(SUBJECT_NAME));
41 |
42 | mCourses = new ArrayList<>();
43 | mCoursesView = (RecyclerView) findViewById(R.id.recyclerview);
44 | mCoursesView.setLayoutManager(new LinearLayoutManager(mCoursesView.getContext()));
45 | mCoursesView.setAdapter(new CoursesNamesRecyclerAdapter(this, mCourses));
46 | this.initialize();
47 | }
48 |
49 | /**********************************************************************************************/
50 | /**********************************************************************************************/
51 |
52 | private void initialize() {
53 | // create a presenter for this view
54 | mSubjectCode = getSubjectCode();
55 | ((CoursesNamesRecyclerAdapter) mCoursesView.getAdapter()).setSubjectCode(mSubjectCode);
56 | mPresenter = UniquePointOfInstanciation.initializeCourses(this, mSubjectCode);
57 | mPresenter.resume();
58 | }
59 |
60 | /**********************************************************************************************/
61 | /**********************************************************************************************/
62 |
63 | public int getSubjectCode() {
64 | Toast.makeText(this, getIntent().getStringExtra(SUBJECT_NAME),Toast.LENGTH_SHORT).show();
65 | return getIntent().getIntExtra(SUBJECT_CODE, 0);
66 | }
67 |
68 | /**********************************************************************************************/
69 | /**********************************************************************************************/
70 |
71 | @Override
72 | public void showProgress() {
73 |
74 | }
75 |
76 | /**********************************************************************************************/
77 | /**********************************************************************************************/
78 |
79 | @Override
80 | public void hideProgress() {
81 |
82 | }
83 |
84 | /**********************************************************************************************/
85 | /**********************************************************************************************/
86 |
87 | @Override
88 | public void showError(String message) {
89 |
90 | }
91 |
92 | /**********************************************************************************************/
93 | /**********************************************************************************************/
94 |
95 | @Override
96 | public void displayCourses(List courses) {
97 | mCourses = CourseModelMapper.transform(courses);
98 | Log.e("dsada", courses.toString());
99 | Log.e("dsada", courses.toString());
100 | mCoursesView.setAdapter(new CoursesNamesRecyclerAdapter(this, mCourses));
101 | ((CoursesNamesRecyclerAdapter) mCoursesView.getAdapter()).setSubjectCode(mSubjectCode);
102 | mCoursesView.getAdapter().notifyDataSetChanged();
103 | mCoursesView.invalidate();
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/activities/EnrollToCourseActivity.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.activities;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 |
6 | import com.clean.R;
7 | import com.clean.presentation.UniquePointOfInstanciation;
8 | import com.clean.presentation.presenters.enroll_to_course.EnrollToCoursePresenter;
9 | import com.clean.presentation.ui.dialogs.NotifyDialog;
10 |
11 | /**
12 | * Created by fabrizio on 07/06/16.
13 | */
14 | public class EnrollToCourseActivity extends AppCompatActivity implements EnrollToCoursePresenter.View{
15 |
16 | public static String COURSE_ID = "course_id";
17 | public static String SUBJECT_CODE = "subject_code";
18 | private EnrollToCoursePresenter mPresenter;
19 |
20 | /**********************************************************************************************/
21 | /**********************************************************************************************/
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstance) {
25 | super.onCreate(savedInstance);
26 | int subjectCode = getSubjectCode();
27 | int courseId = getCourseId();
28 | mPresenter = UniquePointOfInstanciation.initializeEnrollToCourse(this, subjectCode, courseId);
29 | mPresenter.resume();
30 | }
31 |
32 | /**********************************************************************************************/
33 | /**********************************************************************************************/
34 |
35 | public int getSubjectCode() {
36 | return getIntent().getIntExtra(SUBJECT_CODE, 0);
37 | }
38 |
39 | /**********************************************************************************************/
40 | /**********************************************************************************************/
41 |
42 | public int getCourseId() {
43 | return getIntent().getIntExtra(COURSE_ID, 0);
44 | }
45 |
46 | /**********************************************************************************************/
47 | /**********************************************************************************************/
48 |
49 | @Override
50 | public void showProgress() {
51 |
52 | }
53 |
54 | /**********************************************************************************************/
55 | /**********************************************************************************************/
56 |
57 | @Override
58 | public void hideProgress() {
59 |
60 | }
61 |
62 | /**********************************************************************************************/
63 | /**********************************************************************************************/
64 |
65 | @Override
66 | public void showError(String message) {
67 |
68 | }
69 |
70 | /**********************************************************************************************/
71 | /**********************************************************************************************/
72 |
73 | @Override
74 | public void notifyAlreadyEnrolledSubject() {
75 | NotifyDialog.build(this, getString(R.string.error_title), getString(R.string.same_subject)).show();
76 | }
77 |
78 | /**********************************************************************************************/
79 | /**********************************************************************************************/
80 |
81 | @Override
82 | public void notifyEnrolledInSevenCourses() {
83 | NotifyDialog.build(this, getString(R.string.error_title), getString(R.string.limit)).show();
84 | }
85 |
86 | /**********************************************************************************************/
87 | /**********************************************************************************************/
88 |
89 | @Override
90 | public void notifyEnrolled() {
91 | NotifyDialog.build(this, getString(R.string.sucess_title), getString(R.string.sucess_enroll)).show();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/activities/EnrolledCoursesActivity.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.activities;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.util.Log;
8 |
9 | import com.clean.R;
10 | import com.clean.presentation.UniquePointOfInstanciation;
11 | import com.clean.presentation.presenters.BasePresenter;
12 | import com.clean.presentation.presenters.enrolled_courses.EnrolledCoursesPresenter;
13 | import com.clean.presentation.ui.adapters.SimpleStringRecyclerViewAdapter;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | import butterknife.ButterKnife;
19 |
20 | public class EnrolledCoursesActivity extends AppCompatActivity implements EnrolledCoursesPresenter.View {
21 |
22 | private BasePresenter mPresenter;
23 | private RecyclerView mInscriptionsView;
24 | private List mInscriptions;
25 |
26 | /**********************************************************************************************/
27 | /**********************************************************************************************/
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_enrolled_courses);
33 | ButterKnife.bind(this);
34 | getSupportActionBar().setTitle(getString(R.string.inscriptions));
35 |
36 | mInscriptions = new ArrayList<>();
37 | mInscriptionsView = (RecyclerView) findViewById(R.id.recyclerview);
38 | mInscriptionsView.setLayoutManager(new LinearLayoutManager(mInscriptionsView.getContext()));
39 | mInscriptionsView.setAdapter(new SimpleStringRecyclerViewAdapter(this, mInscriptions));
40 | this.initialize();
41 | }
42 |
43 | /**********************************************************************************************/
44 | /**********************************************************************************************/
45 |
46 | private void initialize() {
47 | // create a presenter for this view
48 | mPresenter = UniquePointOfInstanciation.initializeEnrolledCourses(this);
49 | mPresenter.resume();
50 | }
51 |
52 | /**********************************************************************************************/
53 | /**********************************************************************************************/
54 |
55 | @Override
56 | public void showProgress() {
57 |
58 | }
59 |
60 | /**********************************************************************************************/
61 | /**********************************************************************************************/
62 |
63 | @Override
64 | public void hideProgress() {
65 |
66 | }
67 |
68 | /**********************************************************************************************/
69 | /**********************************************************************************************/
70 |
71 | @Override
72 | public void showError(String message) {
73 |
74 | }
75 |
76 | /**********************************************************************************************/
77 | /**********************************************************************************************/
78 |
79 | @Override
80 | public void displayCourses(List courses) {
81 | //mInscriptions = CourseModelMapper.transform(courses);
82 | Log.e("dsada", courses.toString());
83 | Log.e("dsada", courses.toString());
84 | mInscriptions = courses;
85 | mInscriptionsView.setAdapter(new SimpleStringRecyclerViewAdapter(this, mInscriptions));
86 | mInscriptionsView.getAdapter().notifyDataSetChanged();
87 | mInscriptionsView.invalidate();
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/activities/Main2Activity.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.activities;
2 |
3 | import android.content.Intent;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.Button;
8 |
9 | import com.clean.R;
10 | import butterknife.ButterKnife;
11 |
12 | public class Main2Activity extends AppCompatActivity {
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_main2);
18 | ButterKnife.bind(this);
19 |
20 | Button seeEnrolled = (Button) findViewById(R.id.see_enrolled);
21 | Button enroll = (Button) findViewById(R.id.enroll);
22 | setSeeEnrolledBehavior(seeEnrolled);
23 | setEnrollBehavior(enroll);
24 |
25 | }
26 |
27 | /**********************************************************************************************/
28 | /**********************************************************************************************/
29 |
30 | private void setSeeEnrolledBehavior(Button seeEnrolled) {
31 | seeEnrolled.setOnClickListener(new View.OnClickListener() {
32 | @Override
33 | public void onClick(View v) {
34 | Intent intent = new Intent(Main2Activity.this, EnrolledCoursesActivity.class);
35 | startActivity(intent);
36 | }
37 | });
38 | }
39 |
40 | /**********************************************************************************************/
41 | /**********************************************************************************************/
42 |
43 | private void setEnrollBehavior(Button enroll) {
44 | enroll.setOnClickListener(new View.OnClickListener() {
45 | @Override
46 | public void onClick(View v) {
47 | Intent intent = new Intent(Main2Activity.this, MainActivity.class);
48 | startActivity(intent);
49 | }
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/activities/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.activities;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.util.Log;
8 |
9 | import com.clean.R;
10 | import com.clean.presentation.UniquePointOfInstanciation;
11 | import com.clean.presentation.model.SubjectModel;
12 | import com.clean.presentation.presenters.main.MainPresenter;
13 | import com.clean.presentation.presenters.main.MainPresenter.View;
14 | import com.clean.presentation.mapper.SubjectModelMapper;
15 | import com.clean.presentation.ui.adapters.SubjectModelRecyclerViewAdapter;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | import butterknife.ButterKnife;
21 |
22 | public class MainActivity extends AppCompatActivity implements View {
23 |
24 | private MainPresenter mPresenter;
25 | private RecyclerView mSubjectsView;
26 | private List mSubjects;
27 |
28 | /**********************************************************************************************/
29 | /**********************************************************************************************/
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.activity_main);
35 | ButterKnife.bind(this);
36 |
37 | mSubjects = new ArrayList<>();
38 | mSubjectsView = (RecyclerView) findViewById(R.id.recyclerview);
39 | mSubjectsView.setLayoutManager(new LinearLayoutManager(mSubjectsView.getContext()));
40 | mSubjectsView.setAdapter(new SubjectModelRecyclerViewAdapter(this, mSubjects));
41 | this.initialize();
42 | }
43 |
44 | /**********************************************************************************************/
45 | /**********************************************************************************************/
46 |
47 | private void initialize() {
48 | // create a presenter for this view
49 | mPresenter = UniquePointOfInstanciation.initializeGetAvailableSubjects(this);
50 | mPresenter.resume();
51 | }
52 |
53 | /**********************************************************************************************/
54 | /**********************************************************************************************/
55 |
56 | @Override
57 | public void showProgress() {
58 |
59 | }
60 |
61 | /**********************************************************************************************/
62 | /**********************************************************************************************/
63 |
64 | @Override
65 | public void hideProgress() {
66 |
67 | }
68 |
69 | /**********************************************************************************************/
70 | /**********************************************************************************************/
71 |
72 | @Override
73 | public void showError(String message) {
74 |
75 | }
76 |
77 | /**********************************************************************************************/
78 | /**********************************************************************************************/
79 |
80 | @Override
81 | public void displaySubjects(List subjects) {
82 | mSubjects = SubjectModelMapper.transform(subjects);
83 | Log.e("dsada", subjects.toString());
84 | Log.e("dsada", mSubjects.toString());
85 | mSubjectsView.setAdapter(new SubjectModelRecyclerViewAdapter(this, mSubjects));
86 | mSubjectsView.getAdapter().notifyDataSetChanged();
87 | mSubjectsView.invalidate();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/adapters/CoursesNamesRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.adapters;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.util.TypedValue;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.clean.R;
11 | import com.clean.presentation.model.CourseModel;
12 | import com.clean.presentation.ui.dialogs.EnrollToCourseDialog;
13 | import com.clean.presentation.ui.viewholders.ViewHolder;
14 |
15 | import java.util.List;
16 |
17 | /**
18 | * Created by fabrizio on 06/06/16.
19 | */
20 | public class CoursesNamesRecyclerAdapter extends RecyclerView.Adapter {
21 |
22 | private final TypedValue mTypedValue = new TypedValue();
23 | private int mBackground;
24 | private List mValues;
25 | private int mSubjectCode;
26 |
27 | /**********************************************************************************************/
28 | /**********************************************************************************************/
29 |
30 | public CourseModel getValueAt(int position) {
31 | return mValues.get(position);
32 | }
33 |
34 | /**********************************************************************************************/
35 | /**********************************************************************************************/
36 |
37 | public CoursesNamesRecyclerAdapter(Context context, List items) {
38 | context.getTheme().resolveAttribute(R.attr.selectableItemBackground, mTypedValue, true);
39 | mBackground = mTypedValue.resourceId;
40 | mValues = items;
41 | }
42 |
43 | /**********************************************************************************************/
44 | /**********************************************************************************************/
45 |
46 | @Override
47 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
48 | View view = LayoutInflater.from(parent.getContext())
49 | .inflate(R.layout.list_item, parent, false);
50 | view.setBackgroundResource(mBackground);
51 | return new ViewHolder(view);
52 | }
53 |
54 | /**********************************************************************************************/
55 | /**********************************************************************************************/
56 |
57 | @Override
58 | public void onBindViewHolder(final ViewHolder holder, int position) {
59 | //holder.mBoundString = mValues.get(position).get;
60 | final CourseModel course = mValues.get(position);
61 | holder.mTextView.setText("Curso " + course.getId());
62 | final String courseInfo = "Docentes: " + getTeachers(course) + "\n"
63 | + "Horario: " + course.getSchedule() + "\n"
64 | + "Vacantes: " + course.getVacancy();
65 |
66 |
67 | holder.mView.setOnClickListener(new View.OnClickListener() {
68 | @Override
69 | public void onClick(View v) {
70 | Context context = v.getContext();
71 | EnrollToCourseDialog.build(context, courseInfo, course.getId(), mSubjectCode).show();
72 | }
73 | });
74 | }
75 |
76 | /**********************************************************************************************/
77 | /**********************************************************************************************/
78 |
79 | private String getTeachers(CourseModel course) {
80 | String teachers = "";
81 | List teachersList = course.getTeachers();
82 | for (String teacher : teachersList) {
83 | teachers += teacher + ", ";
84 | }
85 | return teachers.substring(0, teachers.length()-2);
86 | }
87 |
88 | /**********************************************************************************************/
89 | /**********************************************************************************************/
90 |
91 | @Override
92 | public int getItemCount() {
93 | return mValues.size();
94 | }
95 |
96 | /**********************************************************************************************/
97 | /**********************************************************************************************/
98 |
99 | public void setSubjectCode(int subjectCode) {
100 | mSubjectCode = subjectCode;
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/adapters/SimpleStringRecyclerViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.adapters;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.util.TypedValue;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 |
12 | import com.clean.R;
13 | import com.clean.presentation.ui.activities.CoursesActivity;
14 | import com.clean.presentation.ui.viewholders.ViewHolder;
15 |
16 | import java.util.List;
17 |
18 | /**
19 | * Created by fabrizio on 26/05/16.
20 | */
21 |
22 | public class SimpleStringRecyclerViewAdapter
23 | extends RecyclerView.Adapter {
24 |
25 | private final TypedValue mTypedValue = new TypedValue();
26 | private int mBackground;
27 | private List mValues;
28 |
29 | /**********************************************************************************************/
30 | /**********************************************************************************************/
31 |
32 | public String getValueAt(int position) {
33 | return mValues.get(position);
34 | }
35 |
36 | /**********************************************************************************************/
37 | /**********************************************************************************************/
38 |
39 | public SimpleStringRecyclerViewAdapter(Context context, List items) {
40 | context.getTheme().resolveAttribute(R.attr.selectableItemBackground, mTypedValue, true);
41 | mBackground = mTypedValue.resourceId;
42 | mValues = items;
43 | }
44 |
45 | /**********************************************************************************************/
46 | /**********************************************************************************************/
47 |
48 | @Override
49 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
50 | View view = LayoutInflater.from(parent.getContext())
51 | .inflate(R.layout.list_item, parent, false);
52 | view.setBackgroundResource(mBackground);
53 | return new ViewHolder(view);
54 | }
55 |
56 | /**********************************************************************************************/
57 | /**********************************************************************************************/
58 |
59 | @Override
60 | public void onBindViewHolder(final ViewHolder holder, int position) {
61 | holder.mBoundString = mValues.get(position);
62 | holder.mTextView.setText(mValues.get(position));
63 |
64 | /*holder.mView.setOnClickListener(new View.OnClickListener() {
65 | @Override
66 | public void onClick(View v) {
67 | Context context = v.getContext();
68 | Intent intent = new Intent(context, CoursesActivity.class);
69 | intent.putExtra(CoursesActivity.SUBJECT_CODE, holder.mBoundString);
70 | context.startActivity(intent);
71 | }
72 | });*/
73 | }
74 |
75 | /**********************************************************************************************/
76 | /**********************************************************************************************/
77 |
78 | @Override
79 | public int getItemCount() {
80 | return mValues.size();
81 | }
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/adapters/SubjectModelRecyclerViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.adapters;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.util.Log;
7 | import android.util.TypedValue;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | import com.clean.R;
13 | import com.clean.presentation.model.SubjectModel;
14 | import com.clean.presentation.ui.activities.CoursesActivity;
15 | import com.clean.presentation.ui.viewholders.ViewHolder;
16 |
17 | import java.util.List;
18 |
19 | /**
20 | * Created by fabrizio on 31/05/16.
21 | */
22 | public class SubjectModelRecyclerViewAdapter extends RecyclerView.Adapter {
23 |
24 | private final TypedValue mTypedValue = new TypedValue();
25 | private int mBackground;
26 | private List mValues;
27 |
28 | /**********************************************************************************************/
29 | /**********************************************************************************************/
30 |
31 | public SubjectModel getValueAt(int position) {
32 | return mValues.get(position);
33 | }
34 |
35 | /**********************************************************************************************/
36 | /**********************************************************************************************/
37 |
38 | public SubjectModelRecyclerViewAdapter(Context context, List items) {
39 | context.getTheme().resolveAttribute(R.attr.selectableItemBackground, mTypedValue, true);
40 | mBackground = mTypedValue.resourceId;
41 | mValues = items;
42 | }
43 |
44 | /**********************************************************************************************/
45 | /**********************************************************************************************/
46 |
47 | @Override
48 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
49 | View view = LayoutInflater.from(parent.getContext())
50 | .inflate(R.layout.list_item, parent, false);
51 | view.setBackgroundResource(mBackground);
52 | return new ViewHolder(view);
53 | }
54 |
55 | /**********************************************************************************************/
56 | /**********************************************************************************************/
57 |
58 | @Override
59 | public void onBindViewHolder(final ViewHolder holder, int position) {
60 | holder.mBoundString = mValues.get(position).getName();
61 | holder.mBoundInt = mValues.get(position).getCode();
62 | holder.mTextView.setText(mValues.get(position).getName());
63 | Log.e("NAME", mValues.get(position).getName());
64 |
65 | holder.mView.setOnClickListener(new View.OnClickListener() {
66 | @Override
67 | public void onClick(View v) {
68 | Context context = v.getContext();
69 | Intent intent = new Intent(context, CoursesActivity.class);
70 | intent.putExtra(CoursesActivity.SUBJECT_NAME, holder.mBoundString);
71 | intent.putExtra(CoursesActivity.SUBJECT_CODE, holder.mBoundInt);
72 | context.startActivity(intent);
73 | }
74 | });
75 | }
76 |
77 | /**********************************************************************************************/
78 | /**********************************************************************************************/
79 |
80 | @Override
81 | public int getItemCount() {
82 | return mValues.size();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/dialogs/EnrollToCourseDialog.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.dialogs;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.support.v7.app.AlertDialog;
8 |
9 | import com.clean.R;
10 | import com.clean.presentation.ui.activities.EnrollToCourseActivity;
11 |
12 | /**
13 | * Created by fabrizio on 06/06/16.
14 | */
15 | public class EnrollToCourseDialog {
16 |
17 |
18 | private EnrollToCourseDialog() {}
19 |
20 | public static AlertDialog build(final Context context, String courseInfo,
21 | final int id, final int subjectCode) {
22 |
23 | return new AlertDialog.Builder(context)
24 | .setTitle(R.string.enroll_title)
25 | .setMessage(courseInfo)
26 | .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
27 | public void onClick(DialogInterface dialog, int which) {
28 | Intent intent = new Intent(context, EnrollToCourseActivity.class);
29 | intent.putExtra(EnrollToCourseActivity.COURSE_ID, id);
30 | intent.putExtra(EnrollToCourseActivity.SUBJECT_CODE, subjectCode);
31 | context.startActivity(intent);
32 | }
33 | })
34 | .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
35 | public void onClick(DialogInterface dialog, int which) {
36 | // do nothing
37 | }
38 | })
39 | .setCancelable(false)
40 | .create();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/dialogs/NotifyDialog.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.dialogs;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.content.Intent;
6 | import android.support.v7.app.AlertDialog;
7 | import android.support.v7.app.AppCompatActivity;
8 |
9 | import com.clean.R;
10 | import com.clean.presentation.ui.activities.EnrollToCourseActivity;
11 |
12 | /**
13 | * Created by fabrizio on 08/06/16.
14 | */
15 | public class NotifyDialog {
16 |
17 |
18 | private NotifyDialog() {}
19 |
20 | public static AlertDialog build(final AppCompatActivity context, String title, String message) {
21 |
22 | return new AlertDialog.Builder(context)
23 | .setTitle(title)
24 | .setMessage(message)
25 | .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
26 | public void onClick(DialogInterface dialog, int which) {
27 | context.finish();
28 | }
29 | })
30 | .setCancelable(false)
31 | .create();
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/presentation/ui/viewholders/ViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.clean.presentation.ui.viewholders;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.View;
5 | import android.widget.ImageView;
6 | import android.widget.TextView;
7 |
8 | import com.clean.R;
9 |
10 | /**
11 | * Created by fabrizio on 26/05/16.
12 | */
13 | public class ViewHolder extends RecyclerView.ViewHolder {
14 | public String mBoundString;
15 | public int mBoundInt;
16 |
17 | public final View mView;
18 | //public final ImageView mImageView;
19 | public final TextView mTextView;
20 |
21 | public ViewHolder(View view) {
22 | super(view);
23 | mView = view;
24 | //mImageView = (ImageView) view.findViewById(R.id.avatar);
25 | mTextView = (TextView) view.findViewById(android.R.id.text1);
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return super.toString() + " '" + mTextView.getText();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/java/com/clean/threading/MainThreadImpl.java:
--------------------------------------------------------------------------------
1 | package com.clean.threading;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | import com.clean.domain.executor.MainThread;
7 |
8 |
9 | /**
10 | * This class makes sure that the runnable we provide will be run on the main UI thread.
11 | */
12 | public class MainThreadImpl implements MainThread {
13 |
14 | private static MainThread sMainThread;
15 |
16 | private Handler mHandler;
17 |
18 | private MainThreadImpl() {
19 | mHandler = new Handler(Looper.getMainLooper());
20 | }
21 |
22 | @Override
23 | public void post(Runnable runnable) {
24 | mHandler.post(runnable);
25 | }
26 |
27 | public static MainThread getInstance() {
28 | if (sMainThread == null) {
29 | sMainThread = new MainThreadImpl();
30 | }
31 |
32 | return sMainThread;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/layout/activity_courses.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/layout/activity_enrolled_courses.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/layout/activity_main2.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
19 |
20 |
25 |
26 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/layout/list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
26 |
27 |
34 |
35 |
40 |
41 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/layout/recycler_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/android/FIUBAPP/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/android/FIUBAPP/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/android/FIUBAPP/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/android/FIUBAPP/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/android/FIUBAPP/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Materias
4 | Materias
5 | Cursos
6 | Inscripciones
7 |
8 |
9 | Inscribirse
10 | Docentes
11 | Vacantes
12 | Error
13 | Ha llegado al limite de cursos disponibles para anotarse
14 | Ya se ha anotado en otro curso de esta materia
15 | Éxito
16 | Se ha inscripto exitosamente al curso
17 |
18 |
19 | Ver inscripciones
20 | Inscribirse
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/android/FIUBAPP/app/src/test/java/com/kodelabs/boilerplate/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.clean;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/android/FIUBAPP/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | maven { url "https://jitpack.io" }
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/android/FIUBAPP/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/android/FIUBAPP/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/android/FIUBAPP/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/FIUBAPP/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/android/FIUBAPP/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/FIUBAPP/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/api/courses.json:
--------------------------------------------------------------------------------
1 | {"courses": [
2 | {"id": 1, "teachers": ["profesor1"], "schedule": "Lun y Mie 18 a 19", "classroom": "1", "vacancy": 20},
3 | {"id": 2, "teachers": ["proffesor2"], "schedule": "Mar y Mie 18 a 19", "classroom": "2", "vacancy": 20},
4 | {"id": 3, "teachers": ["proffesor3"], "schedule": "Lun y Jue 18 a 19", "classroom": "3", "vacancy": 20},
5 | {"id": 4, "teachers": ["proffesor4"], "schedule": "Mar y Vie 18 a 19", "classroom": "4", "vacancy": 20},
6 | {"id": 5, "teachers": ["proffesor5"], "schedule": "Lun y Vie 18 a 19", "classroom": "5", "vacancy": 10},
7 | {"id": 6, "teachers": ["proffesor6"], "schedule": "Mar y Jue 18 a 19", "classroom": "6", "vacancy": 5},
8 | {"id": 7, "teachers": ["proffesor7"], "schedule": "Lun y Mie 10 a 12", "classroom": "7", "vacancy": 10},
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/api/subjects.json:
--------------------------------------------------------------------------------
1 | {"subjects": [
2 | {"name": "Análisis Matemático IIA", "code": 61.03, "Departament": "Matemática"},
3 | {"name": "Algebra II", "code": 61.08, "Departament": "Matemática"},
4 | {"name": "Análisis Matemático IIIA", "code": 61.10, "Departament": "Matemática"},
5 | {"name": "Probabilidad", "code": 61.09, "Departament": "Matemática"},
6 | {"name": "Algoritmos y Programación I", "code": 75.40, "Departament": "Computación"},
7 | {"name": "Algoritmos y Programación II", "code": 75.41, "Departament": "Computación"},
8 | {"name": "Algoritmos y Programación III", "code": 75.07, "Departament": "Computación"},
9 | {"name": "Algoritmos y Programación I", "code": 75.40, "Departament": "Computación"},
10 | {"name": "Análisis Numérico", "code": 75.12, "Departament": "Computación"},
11 | {"name": "Organización de Datos", "code": 75.06, "Departament": "Computación"},
12 | {"name": "Taller de Programación I", "code": 75.42, "Departament": "Computación"},
13 | {"name": "Taller de Programación II", "code": 75.52, "Departament": "Computación"},
14 | {"name": "Base de Datos", "code": 75.15, "Departament": "Computación"},
15 | {"name": "Técnicas de Diseño", "code": 75.10, "Departament": "Computación"},
16 | {"name": "Análisis de la Información", "code": 75.09, "Departament": "Computación"},
17 | {"name": "Sistemas Operativos", "code": 75.40, "Departament": "Computación"},
18 | {"name": "Introducción a los Sistemas Distribuidos", "code": 75.43, "Departament": "Computación"},
19 | {"name": "Laboratorio", "code": 66.02, "Departament": "Electrónica"},
20 | {"name": "Estructura del Computador", "code": 66.70, "Departament": "Electrónica"},
21 | {"name": "Organización de Computadoras", "code": 66.20, "Departament": "Electrónica"},
22 | {"name": "Laboratorio", "code": 66.02, "Departament": "Electrónica"},
23 | {"name": "Quimica", "code": 63.01, "Departament": "Quimica"}
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | #
2 | # Xcode
3 | #
4 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
5 | #
6 | # https://github.com/github/gitignore/blob/master/Swift.gitignore
7 | #
8 |
9 | ## Build generated
10 | build/
11 | DerivedData/
12 |
13 | ## Various settings
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata/
23 |
24 | ## Other
25 | *.moved-aside
26 | *.xcuserstate
27 |
28 | ## Obj-C/Swift specific
29 | *.hmap
30 | *.ipa
31 | *.dSYM.zip
32 | *.dSYM
33 |
34 | ## Playgrounds
35 | timeline.xctimeline
36 | playground.xcworkspace
37 |
38 | # Swift Package Manager
39 | #
40 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
41 | # Packages/
42 | .build/
43 |
44 | # CocoaPods
45 | #
46 | # We recommend against adding the Pods directory to your .gitignore. However
47 | # you should judge for yourself, the pros and cons are mentioned at:
48 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
49 | #
50 | Pods/
51 |
52 | # Carthage
53 | #
54 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
55 | # Carthage/Checkouts
56 |
57 | Carthage/Build
58 |
59 | # fastlane
60 | #
61 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
62 | # screenshots whenever they are needed.
63 | # For more information about the recommended setup visit:
64 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
65 |
66 | fastlane/report.xml
67 | fastlane/Preview.html
68 | fastlane/screenshots
69 | fastlane/test_output
70 |
--------------------------------------------------------------------------------
/ios/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules: # rule identifiers to exclude from running
2 | - trailing_whitespace
3 | - line_length
4 | - nesting
5 |
6 | excluded: # paths to ignore during linting. Takes precedence over `included`.
7 | - Carthage
8 | - Pods
9 |
10 | # configurable rules can be customized from this configuration file
11 | variable_name:
12 | excluded: # excluded via string array
13 | - id
14 |
--------------------------------------------------------------------------------
/ios/FIUBA.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/FIUBA.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/FIUBA/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // FIUBA
4 | //
5 | // Created by Ezequiel Pérez Dittler on 25/5/16.
6 | // Copyright © 2016 FIUBA. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | let UDDataBaseIsLoaded = "DataBaseIsLoaded"
12 |
13 | @UIApplicationMain
14 | class AppDelegate: UIResponder, UIApplicationDelegate {
15 |
16 | var window: UIWindow?
17 |
18 |
19 | func application(_ application: UIApplication,
20 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
21 | // Override point for customization after application launch.
22 |
23 | checkDataBase()
24 |
25 | return true
26 | }
27 |
28 | func applicationWillResignActive(_ application: UIApplication) {
29 | // Sent when the application is about to move from active to inactive state.
30 | // This can occur for certain types of temporary interruptions (such as
31 | // an incoming phone call or SMS message) or when the user quits the
32 | // application and it begins the transition to the background state.
33 | // Use this method to pause ongoing tasks, disable timers, and throttle
34 | // down OpenGL ES frame rates. Games should use this method to pause the game.
35 | }
36 |
37 | func applicationDidEnterBackground(_ application: UIApplication) {
38 | // Use this method to release shared resources, save user data,
39 | // invalidate timers, and store enough application state information to
40 | // restore your application to its current state in case it is terminated later.
41 | // If your application supports background execution, this method is
42 | // called instead of applicationWillTerminate: when the user quits.
43 | }
44 |
45 | func applicationWillEnterForeground(_ application: UIApplication) {
46 | // Called as part of the transition from the background to the inactive state;
47 | // here you can undo many of the changes made on entering the background.
48 | }
49 |
50 | func applicationDidBecomeActive(_ application: UIApplication) {
51 | // Restart any tasks that were paused (or not yet started) while
52 | // the application was inactive. If the application was previously in
53 | // the background, optionally refresh the user interface.
54 | }
55 |
56 | func applicationWillTerminate(_ application: UIApplication) {
57 | // Called when the application is about to terminate. Save data if appropriate.
58 | // See also applicationDidEnterBackground:.
59 | }
60 |
61 | func checkDataBase() {
62 | let userDefaults = UserDefaults.standard
63 | let DBIsLoaded = userDefaults.bool(forKey: UDDataBaseIsLoaded)
64 | if !DBIsLoaded {
65 | loadDataBase()
66 | userDefaults.set(true, forKey: UDDataBaseIsLoaded)
67 | userDefaults.synchronize()
68 | }
69 | }
70 |
71 | func loadDataBase() {
72 | let jsonCourseWorker = CoursesWorker(coursesStore: CoursesJsonStore())
73 | jsonCourseWorker.fetchCourses { (courses) in
74 | let rmlWorker = CoursesWorker(coursesStore: CoursesRealmStore())
75 | rmlWorker.createCourses(courses)
76 | }
77 | let jsonSubjectsWorker = SubjectsWorker(subjectsStore: SubjectsJsonStore())
78 | jsonSubjectsWorker.fetchSubjects { (subjects) in
79 | let rmlWorker = SubjectsWorker(subjectsStore: SubjectsRealmStore())
80 | rmlWorker.createSubjects(subjects)
81 | }
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "icon58.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "icon87.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "40x40",
17 | "idiom" : "iphone",
18 | "filename" : "icon80.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "icon120.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "60x60",
29 | "idiom" : "iphone",
30 | "filename" : "icon120-1.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "icon180.png",
37 | "scale" : "3x"
38 | }
39 | ],
40 | "info" : {
41 | "version" : 1,
42 | "author" : "xcode"
43 | }
44 | }
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon120-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon120-1.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon120.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon180.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon58.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon80.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/AppIcon.appiconset/icon87.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/Logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "FIUBALogo.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "FIUBALogo2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "FIUBALogo3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/Logo.imageset/FIUBALogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/Logo.imageset/FIUBALogo.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/Logo.imageset/FIUBALogo2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/Logo.imageset/FIUBALogo2x.png
--------------------------------------------------------------------------------
/ios/FIUBA/Assets.xcassets/Logo.imageset/FIUBALogo3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/ios/FIUBA/Assets.xcassets/Logo.imageset/FIUBALogo3x.png
--------------------------------------------------------------------------------
/ios/FIUBA/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/ios/FIUBA/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 0.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/ios/FIUBA/Models/Course.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CourseModels.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | struct Course {
9 | var id: String?
10 | var subjectId: String?
11 | var number: Int?
12 | var teachers: String?
13 | var vacancies: Int?
14 | var enrolled: Bool?
15 | }
16 |
--------------------------------------------------------------------------------
/ios/FIUBA/Models/Subject.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Subject.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | struct Subject {
9 | var id: String?
10 | var code: String?
11 | var name: String?
12 | //var courses: [Course]?
13 | }
14 |
--------------------------------------------------------------------------------
/ios/FIUBA/Resources/Json/courses.json:
--------------------------------------------------------------------------------
1 | {
2 | "courses": [{
3 | "id": "711201",
4 | "subjectId": "7112",
5 | "number": 1,
6 | "teachers": "Reyes-Barmack-Zammarano-Frutos-Vever",
7 | "schedule": "Martes 17:00 23:00",
8 | "classroom": "LH-106",
9 | "vacancy": 130
10 | },
11 | {
12 | "id": "711401",
13 | "subjectId": "7114",
14 | "number": 1,
15 | "teachers": "Ramos-Ramonet-Navarro Pierre-Levy",
16 | "schedule": "Martes 18:00 a 21:00",
17 | "classroom": "LH-6",
18 | "vacancy": 15
19 | },
20 | {
21 | "id": "711402",
22 | "subjectId": "7114",
23 | "number": 2,
24 | "teachers": "Ramos-Ramonet-Oitana",
25 | "schedule": "Miércoles 19:00 a 22:00",
26 | "classroom": "LH-12",
27 | "vacancy": 15
28 | },
29 | {
30 | "id": "711403",
31 | "subjectId": "7114",
32 | "number": 3,
33 | "teachers": "Ramos-Ramonet-Echevarria",
34 | "schedule": "Martes 9:00 a 12:00",
35 | "classroom": "LH-103",
36 | "vacancy": 15
37 | },
38 | {
39 | "id": "711404",
40 | "subjectId": "7114",
41 | "number": 4,
42 | "teachers": "Ramos-Ramonet-Colombo-Marin",
43 | "schedule": "Sábado 10:00 a 13:00",
44 | "classroom": "LH-102",
45 | "vacancy": 15
46 | },
47 | {
48 | "id": "750801",
49 | "subjectId": "7508",
50 | "number": 1,
51 | "teachers": "Clua-Fernandez-Abraham-Muccio",
52 | "schedule": "Martes y Jueves 19:00 a 22:00",
53 | "classroom": "PC-414",
54 | "vacancy": 60
55 | },
56 | {
57 | "id": "750901",
58 | "subjectId": "7509",
59 | "number": 1,
60 | "teachers": "Gonzalez-Turri-Marcarian",
61 | "schedule": "Lunes y Miércoles 19:00 a 22:00",
62 | "classroom": "PC-303",
63 | "vacancy": 60
64 | },
65 | {
66 | "id": "750902",
67 | "subjectId": "7509",
68 | "number": 2,
69 | "teachers": "Gonzalez-Rivadulla-Sualdea",
70 | "schedule": "Lunes y Viernes 19:00 a 22:00",
71 | "classroom": "PC-303",
72 | "vacancy": 90
73 | },
74 | {
75 | "id": "750903",
76 | "subjectId": "7509",
77 | "number": 3,
78 | "teachers": "Villagra-Locane-Fernandez",
79 | "schedule": "Lunes y Jueves 18:30 a 21:30",
80 | "classroom": "PC-303",
81 | "vacancy": 30
82 | }]
83 | }
84 |
--------------------------------------------------------------------------------
/ios/FIUBA/Resources/Json/subjects.json:
--------------------------------------------------------------------------------
1 | {
2 | "subjects": [{
3 | "id": "7112",
4 | "name": "Estructura de las Organizaciones",
5 | "code": "71.12",
6 | },
7 | {
8 | "id": "7114",
9 | "name": "Modelos y Optimización I",
10 | "code": "71.14",
11 | },
12 | {
13 | "id": "7508",
14 | "name": "Sistemas Operativos",
15 | "code": "75.08",
16 | },
17 | {
18 | "id": "7509",
19 | "name": "Análisis de la Información",
20 | "code": "75.09",
21 | }]
22 | }
23 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListCourses/ListCoursesConfigurator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListCoursesConfigurator.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | // MARK: Connect View, Interactor, and Presenter
9 |
10 | extension ListCoursesViewController {
11 |
12 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
13 | router.passDataToNextScene(segue)
14 | }
15 |
16 | }
17 |
18 | class ListCoursesConfigurator {
19 |
20 | // MARK: Object lifecycle
21 |
22 | static let sharedInstance: ListCoursesConfigurator = {
23 | let instance = ListCoursesConfigurator()
24 | return instance
25 | }()
26 |
27 | // MARK: Configuration
28 |
29 | func configure(_ viewController: ListCoursesViewController) {
30 | let router = ListCoursesRouter()
31 | router.viewController = viewController
32 |
33 | let presenter = ListCoursesPresenter()
34 | presenter.output = viewController
35 |
36 | let interactor = ListCoursesInteractor()
37 | interactor.output = presenter
38 | interactor.worker = ListCoursesWorker()
39 |
40 | viewController.output = interactor
41 | viewController.router = router
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListCourses/ListCoursesInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListCoursesInteractor.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | protocol ListCoursesInteractorInput {
9 | func fetchCourses(_ request: ListCourses.Request)
10 | func selectCourse(_ request: ListCourses.SelectCourse.Request)
11 | func enrollCourse(_ request: ListCourses.EnrollCourse.Request)
12 |
13 | var subject: Subject! { get set }
14 | }
15 |
16 | protocol ListCoursesInteractorOutput {
17 | func presentFetchedCourses(_ response: ListCourses.Response)
18 | func presentEnrollCourseConfirmation(_ response: ListCourses.SelectCourse.Response)
19 | func presentEnrollCourseResult(_ response: ListCourses.EnrollCourse.Response)
20 | }
21 |
22 | protocol ListCoursesWorkerProtocol {
23 | func fetchCoursesBySubject(_ subject: Subject, completionHandler: (_ courses: [Course]) -> Void)
24 | func fetchEnrolledCourses(_ completionHandler: (_ courses: [Course]) -> Void)
25 | func enrollCourse(_ id: String)
26 | }
27 |
28 | class ListCoursesInteractor: ListCoursesInteractorInput {
29 |
30 | var output: ListCoursesInteractorOutput!
31 | var worker: ListCoursesWorkerProtocol!
32 |
33 | var subject: Subject!
34 | var courses: [Course]?
35 |
36 | // MARK: Business logic
37 |
38 | func fetchCourses(_ request: ListCourses.Request) {
39 | worker.fetchCoursesBySubject(subject) { (courses) in
40 | self.courses = courses
41 | let response = ListCourses.Response(courses: courses)
42 | self.output.presentFetchedCourses(response)
43 | }
44 | }
45 |
46 | func selectCourse(_ request: ListCourses.SelectCourse.Request) {
47 | guard let courses = self.courses else { return }
48 | guard !courses.isEmpty else { return }
49 |
50 | let index = courses.index { (course) -> Bool in
51 | return request.id == course.id
52 | }
53 |
54 | guard let aindex = index else { return }
55 | output.presentEnrollCourseConfirmation(ListCourses.SelectCourse.Response(course: courses[aindex]))
56 | }
57 |
58 | func enrollCourse(_ request: ListCourses.EnrollCourse.Request) {
59 | if !isEnrolledCourse() {
60 | worker.fetchEnrolledCourses({ (courses) in
61 | if courses.count < 3 {
62 | NSLog("Enroll!!")
63 | self.enrollCourse(request.id)
64 | } else {
65 | NSLog("Not Enroll :(")
66 | self.notEnrollCourse("No se ha podido inscribir. Ya se ha superado el límite de inscripciones.")
67 | }
68 | })
69 | } else {
70 | NSLog("Not Enroll :(")
71 | notEnrollCourse("No se ha podido inscribir. Ya se encuentra inscipto en un curso de la asignatura.")
72 | }
73 | }
74 |
75 | fileprivate func isEnrolledCourse() -> Bool {
76 | guard let courses = self.courses else { return false }
77 | guard !courses.isEmpty else { return false }
78 |
79 | let enrolledCourses = courses.filter { (course) -> Bool in
80 | return course.enrolled ?? false
81 | }
82 | return !enrolledCourses.isEmpty
83 | }
84 |
85 | fileprivate func enrollCourse(_ id: String) {
86 | worker.enrollCourse(id)
87 | output.presentEnrollCourseResult(ListCourses.EnrollCourse.Response(
88 | enrollSuccess: true,
89 | title: "Inscripción existosa",
90 | message: "Se ha inscripto correctamente al curso"))
91 | }
92 |
93 | fileprivate func notEnrollCourse(_ message: String) {
94 | output.presentEnrollCourseResult(ListCourses.EnrollCourse.Response(
95 | enrollSuccess: false,
96 | title: "Inscripción fallida",
97 | message: message))
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListCourses/ListCoursesModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListCoursesModels.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | struct ListCourses {
9 |
10 | struct Request {
11 | }
12 |
13 | struct Response {
14 | var courses: [Course]
15 | }
16 |
17 | struct ViewModel {
18 |
19 | struct DisplayedCourse {
20 | var id: String
21 | var number: Int
22 | var teachers: String
23 | var vacancies: Int
24 | var enrolled: Bool
25 | }
26 |
27 | var displayedCourses: [DisplayedCourse]
28 | }
29 |
30 | // MARK: - Select Course
31 |
32 | struct SelectCourse {
33 |
34 | struct Request {
35 | var id: String
36 | }
37 |
38 | struct Response {
39 | var course: Course
40 | }
41 |
42 | struct ViewModel {
43 | var id: String
44 | var number: Int
45 | var teachers: String
46 | var vacancies: Int
47 | }
48 |
49 | }
50 |
51 | // MARK: - Enroll Course
52 |
53 | struct EnrollCourse {
54 |
55 | struct Request {
56 | var id: String
57 | }
58 |
59 | struct Response {
60 | var enrollSuccess: Bool
61 | var title: String
62 | var message: String
63 | }
64 |
65 | struct ViewModel {
66 | var enrollSuccess: Bool
67 | var title: String
68 | var message: String
69 | }
70 |
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListCourses/ListCoursesPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListCoursesPresenter.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ListCoursesPresenter: ListCoursesInteractorOutput {
9 |
10 | weak var output: ListCoursesViewProtocol!
11 |
12 | // MARK: Presentation logic
13 |
14 | func presentFetchedCourses(_ response: ListCourses.Response) {
15 | var displayedCourses: [ListCourses.ViewModel.DisplayedCourse] = []
16 | for course in response.courses {
17 | let displayedCourse = ListCourses.ViewModel.DisplayedCourse(
18 | id: course.id ?? "",
19 | number: course.number ?? 0,
20 | teachers: course.teachers ?? "",
21 | vacancies: course.vacancies ?? 0,
22 | enrolled: course.enrolled ?? false)
23 | displayedCourses.append(displayedCourse)
24 | }
25 | let viewModel = ListCourses.ViewModel(displayedCourses: displayedCourses)
26 | output.displayFetchedCourses(viewModel)
27 | }
28 |
29 | func presentEnrollCourseConfirmation(_ response: ListCourses.SelectCourse.Response) {
30 | let viewModel = ListCourses.SelectCourse.ViewModel(
31 | id: response.course.id ?? "",
32 | number: response.course.number ?? 0,
33 | teachers: response.course.teachers ?? "",
34 | vacancies: response.course.vacancies ?? 0)
35 | output.displayEnrollCourseConfirmation(viewModel)
36 | }
37 |
38 | func presentEnrollCourseResult(_ response: ListCourses.EnrollCourse.Response) {
39 | let viewModel = ListCourses.EnrollCourse.ViewModel(
40 | enrollSuccess: response.enrollSuccess,
41 | title: response.title,
42 | message: response.message)
43 | output.displayEnrollCourseResult(viewModel)
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListCourses/ListCoursesRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListCoursesRouter.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | protocol ListCoursesRouterProtocol {
9 | func navigateToSomewhere()
10 | }
11 |
12 | class ListCoursesRouter: ListCoursesRouterProtocol {
13 |
14 | weak var viewController: ListCoursesViewController!
15 |
16 | // MARK: Navigation
17 |
18 | func navigateToSomewhere() {
19 | // NOTE: Teach the router how to navigate to another scene. Some examples follow:
20 |
21 | // 1. Trigger a storyboard segue
22 | // viewController.performSegueWithIdentifier("ShowSomewhereScene", sender: nil)
23 |
24 | // 2. Present another view controller programmatically
25 | // viewController.presentViewController(someWhereViewController, animated: true, completion: nil)
26 |
27 | // 3. Ask the navigation controller to push another view controller onto the stack
28 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
29 |
30 | // 4. Present a view controller from a different storyboard
31 | // let storyboard = UIStoryboard(name: "OtherThanMain", bundle: nil)
32 | // let someWhereViewController = storyboard.instantiateInitialViewController() as! SomeWhereViewController
33 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
34 | }
35 |
36 | // MARK: Communication
37 |
38 | func passDataToNextScene(_ segue: UIStoryboardSegue) {
39 | // NOTE: Teach the router which scenes it can communicate with
40 |
41 | if segue.identifier == "ShowSomewhereScene" {
42 | passDataToSomewhereScene(segue)
43 | }
44 | }
45 |
46 | fileprivate func passDataToSomewhereScene(_ segue: UIStoryboardSegue) {
47 | // NOTE: Teach the router how to pass data to the next scene
48 |
49 | // let someWhereViewController = segue.destinationViewController as! SomeWhereViewController
50 | // someWhereViewController.output.name = viewController.output.name
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListCourses/ListCoursesWorker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListCoursesWorker.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ListCoursesWorker: ListCoursesWorkerProtocol {
9 |
10 | let coursesWorker: CoursesWorker = CoursesWorker(coursesStore: CoursesRealmStore())
11 |
12 | // MARK: Business Logic
13 |
14 | func fetchCoursesBySubject(_ subject: Subject, completionHandler: (_ courses: [Course]) -> Void) {
15 | coursesWorker.fetchCoursesBySubject(subject) { (courses) in
16 | completionHandler(courses)
17 | }
18 | }
19 |
20 | func fetchEnrolledCourses(_ completionHandler: (_ courses: [Course]) -> Void) {
21 | coursesWorker.fetchEnrolledCourses { (result) in
22 | completionHandler(result)
23 | }
24 | }
25 |
26 | func enrollCourse(_ id: String) {
27 | coursesWorker.fetchCourse(id) { (course) in
28 | guard var course = course else { return }
29 | course.enrolled = true
30 | if course.vacancies != nil {
31 | course.vacancies = (course.vacancies! - 1)
32 | }
33 | self.coursesWorker.updateCourse(course)
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListEnrolledCourses/ListEnrolledCoursesConfigurator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListEnrolledCoursesConfigurator.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | // MARK: Connect View, Interactor, and Presenter
9 |
10 | extension ListEnrolledCoursesViewController {
11 |
12 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
13 | router.passDataToNextScene(segue)
14 | }
15 |
16 | }
17 |
18 | class ListEnrolledCoursesConfigurator {
19 |
20 | // MARK: Object lifecycle
21 |
22 | class var sharedInstance: ListEnrolledCoursesConfigurator {
23 | let instance = ListEnrolledCoursesConfigurator()
24 | return instance
25 | }
26 |
27 | // MARK: Configuration
28 |
29 | func configure(_ viewController: ListEnrolledCoursesViewController) {
30 | let router = ListEnrolledCoursesRouter()
31 | router.viewController = viewController
32 |
33 | let presenter = ListEnrolledCoursesPresenter()
34 | presenter.output = viewController
35 |
36 | let interactor = ListEnrolledCoursesInteractor()
37 | interactor.output = presenter
38 |
39 | viewController.output = interactor
40 | viewController.router = router
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListEnrolledCourses/ListEnrolledCoursesInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListEnrolledCoursesInteractor.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | protocol ListEnrolledCoursesInteractorInput {
9 | func fetchEnrolledCourses(_ request: ListEnrolledCourses.Request)
10 | func unenrollCourse(_ request: ListEnrolledCourses.UnenrollCourse.Request)
11 | }
12 |
13 | protocol ListEnrolledCoursesInteractorOutput {
14 | func presentFetchedEnrolledCourses(_ response: ListEnrolledCourses.Response)
15 | func presentUnenrollCourseResult(_ response: ListEnrolledCourses.UnenrollCourse.Response)
16 | }
17 |
18 | protocol ListEnrolledCoursesWorkerProtocol {
19 | func fetchEnrolledCourses(_ completionHandler: (_ courses: [Course]) -> Void)
20 | func unenrollCourse(_ id: String)
21 | }
22 |
23 | class ListEnrolledCoursesInteractor: ListEnrolledCoursesInteractorInput {
24 |
25 | var output: ListEnrolledCoursesInteractorOutput!
26 | var worker: ListEnrolledCoursesWorkerProtocol! = ListEnrolledCoursesWorker()
27 |
28 | var enrolledCourses: [Course]?
29 |
30 | // MARK: Business logic
31 |
32 | func fetchEnrolledCourses(_ request: ListEnrolledCourses.Request) {
33 | worker.fetchEnrolledCourses { (courses) in
34 | self.enrolledCourses = courses
35 | let response = ListEnrolledCourses.Response(courses: courses)
36 | self.output.presentFetchedEnrolledCourses(response)
37 | }
38 | }
39 |
40 | func unenrollCourse(_ request: ListEnrolledCourses.UnenrollCourse.Request) {
41 | worker.unenrollCourse(request.id)
42 | output.presentUnenrollCourseResult(ListEnrolledCourses.UnenrollCourse.Response(
43 | unenrollSuccess: true,
44 | title: "Desuscripción existosa",
45 | message: "Se ha desuscripto correctamente del curso."))
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListEnrolledCourses/ListEnrolledCoursesModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListEnrolledCoursesModels.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | struct ListEnrolledCourses {
9 |
10 | struct Request {
11 | }
12 |
13 | struct Response {
14 | var courses: [Course]
15 | }
16 |
17 | struct ViewModel {
18 |
19 | struct DisplayedCourse {
20 | var id: String
21 | var number: Int
22 | var teachers: String
23 | var vacancies: Int
24 | var enrolled: Bool
25 | }
26 |
27 | var displayedCourses: [DisplayedCourse]
28 | }
29 |
30 | struct UnenrollCourse {
31 |
32 | struct Request {
33 | var id: String
34 | }
35 |
36 | struct Response {
37 | var unenrollSuccess: Bool
38 | var title: String
39 | var message: String
40 | }
41 |
42 | struct ViewModel {
43 | var unenrollSuccess: Bool
44 | var title: String
45 | var message: String
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListEnrolledCourses/ListEnrolledCoursesPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListEnrolledCoursesPresenter.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ListEnrolledCoursesPresenter: ListEnrolledCoursesInteractorOutput {
9 |
10 | weak var output: ListEnrolledCoursesViewInput!
11 |
12 | // MARK: Presentation logic
13 |
14 | func presentFetchedEnrolledCourses(_ response: ListEnrolledCourses.Response) {
15 | var displayedCourses: [ListEnrolledCourses.ViewModel.DisplayedCourse] = []
16 | for course in response.courses {
17 | let displayedCourse = ListEnrolledCourses.ViewModel.DisplayedCourse(
18 | id: course.id ?? "",
19 | number: course.number ?? 0,
20 | teachers: course.teachers ?? "",
21 | vacancies: course.vacancies ?? 0,
22 | enrolled: course.enrolled ?? false)
23 | displayedCourses.append(displayedCourse)
24 | }
25 | let viewModel = ListEnrolledCourses.ViewModel(displayedCourses: displayedCourses)
26 | output.displayFetchedEnrolledCourses(viewModel)
27 | }
28 |
29 | func presentUnenrollCourseResult(_ response: ListEnrolledCourses.UnenrollCourse.Response) {
30 | let viewModel = ListEnrolledCourses.UnenrollCourse.ViewModel(
31 | unenrollSuccess: response.unenrollSuccess,
32 | title: response.title,
33 | message: response.message)
34 | output.displayUnenrollCourseResult(viewModel)
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListEnrolledCourses/ListEnrolledCoursesRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListEnrolledCoursesRouter.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | protocol ListEnrolledCoursesRouterInput {
9 | func navigateToSomewhere()
10 | }
11 |
12 | class ListEnrolledCoursesRouter: ListEnrolledCoursesRouterInput {
13 |
14 | weak var viewController: ListEnrolledCoursesViewController!
15 |
16 | // MARK: Navigation
17 |
18 | func navigateToSomewhere() {
19 | // NOTE: Teach the router how to navigate to another scene. Some examples follow:
20 |
21 | // 1. Trigger a storyboard segue
22 | // viewController.performSegueWithIdentifier("ShowSomewhereScene", sender: nil)
23 |
24 | // 2. Present another view controller programmatically
25 | // viewController.presentViewController(someWhereViewController, animated: true, completion: nil)
26 |
27 | // 3. Ask the navigation controller to push another view controller onto the stack
28 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
29 |
30 | // 4. Present a view controller from a different storyboard
31 | // let storyboard = UIStoryboard(name: "OtherThanMain", bundle: nil)
32 | // let someWhereViewController = storyboard.instantiateInitialViewController() as! SomeWhereViewController
33 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
34 | }
35 |
36 | // MARK: Communication
37 |
38 | func passDataToNextScene(_ segue: UIStoryboardSegue) {
39 | // NOTE: Teach the router which scenes it can communicate with
40 |
41 | if segue.identifier == "ShowSomewhereScene" {
42 | passDataToSomewhereScene(segue)
43 | }
44 | }
45 |
46 | func passDataToSomewhereScene(_ segue: UIStoryboardSegue) {
47 | // NOTE: Teach the router how to pass data to the next scene
48 |
49 | // let someWhereViewController = segue.destinationViewController as! SomeWhereViewController
50 | // someWhereViewController.output.name = viewController.output.name
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListEnrolledCourses/ListEnrolledCoursesWorker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListEnrolledCoursesWorker.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ListEnrolledCoursesWorker: ListEnrolledCoursesWorkerProtocol {
9 |
10 | let coursesWorker: CoursesWorker = CoursesWorker(coursesStore: CoursesRealmStore())
11 |
12 | // MARK: Business Logic
13 |
14 | func fetchEnrolledCourses(_ completionHandler: (_ courses: [Course]) -> Void) {
15 | coursesWorker.fetchEnrolledCourses { (result) in
16 | completionHandler(result)
17 | }
18 | }
19 |
20 | func unenrollCourse(_ id: String) {
21 | coursesWorker.fetchCourse(id) { (course) in
22 | guard var course = course else { return }
23 | course.enrolled = false
24 | if course.vacancies != nil {
25 | course.vacancies = (course.vacancies! + 1)
26 | }
27 | self.coursesWorker.updateCourse(course)
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListSubjects/ListSubjectsConfigurator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSubjectsConfigurator.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | // MARK: Connect View, Interactor, and Presenter
9 |
10 | extension ListSubjectsViewController {
11 |
12 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
13 | router.passDataToNextScene(segue)
14 | }
15 |
16 | }
17 |
18 | class ListSubjectsConfigurator {
19 |
20 | // MARK: Object lifecycle
21 |
22 | static let sharedInstance: ListSubjectsConfigurator = {
23 | let instance = ListSubjectsConfigurator()
24 | return instance
25 | }()
26 |
27 | // MARK: Configuration
28 |
29 | func configure(_ viewController: ListSubjectsViewController) {
30 | let router = ListSubjectsRouter()
31 | router.viewController = viewController
32 |
33 | let presenter = ListSubjectsPresenter()
34 | presenter.output = viewController
35 |
36 | let interactor = ListSubjectsInteractor()
37 | interactor.output = presenter
38 |
39 | viewController.output = interactor
40 | viewController.router = router
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListSubjects/ListSubjectsInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSubjectsInteractor.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | protocol ListSubjectsInteractorInput {
9 | func fetchSubjects(_ request: ListSubjects.Request)
10 | var subjects: [Subject]? { get }
11 | }
12 |
13 | protocol ListSubjectsInteractorOutput {
14 | func presentFetchedSubjects(_ response: ListSubjects.Response)
15 | }
16 |
17 | protocol ListSubjectsWorkerProtocol {
18 | func fetchSubjects(_ completionHandler: @escaping (_ subjects: [Subject]) -> Void)
19 | }
20 |
21 | class ListSubjectsInteractor: ListSubjectsInteractorInput {
22 | var output: ListSubjectsInteractorOutput!
23 | var worker: ListSubjectsWorkerProtocol! = ListSubjectsWorker()
24 |
25 | var subjects: [Subject]?
26 |
27 | // MARK: Business logic
28 |
29 | func fetchSubjects(_ request: ListSubjects.Request) {
30 | worker.fetchSubjects { (subjects) in
31 | self.subjects = subjects
32 | let response = ListSubjects.Response(subjects: subjects)
33 | self.output.presentFetchedSubjects(response)
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListSubjects/ListSubjectsModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSubjectsModels.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | struct ListSubjects {
9 |
10 | struct Request {
11 | }
12 |
13 | struct Response {
14 | var subjects: [Subject]
15 | }
16 |
17 | struct ViewModel {
18 |
19 | struct DisplayedSubject {
20 | var id: String
21 | var code: String
22 | var name: String
23 | }
24 |
25 | var displayedSubjects: [DisplayedSubject]
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListSubjects/ListSubjectsPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSubjectsPresenter.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ListSubjectsPresenter: ListSubjectsInteractorOutput {
9 | weak var output: ListSubjectsViewProtocol!
10 |
11 | // MARK: Presentation logic
12 |
13 | func presentFetchedSubjects(_ response: ListSubjects.Response) {
14 | var displayedSubjects: [ListSubjects.ViewModel.DisplayedSubject] = []
15 |
16 | for subject in response.subjects {
17 | let displayedSubject = ListSubjects.ViewModel.DisplayedSubject(
18 | id: subject.id ?? "", code: subject.code ?? "", name: subject.name ?? "")
19 | displayedSubjects.append(displayedSubject)
20 | }
21 | output.displayFetchedSubjects(ListSubjects.ViewModel(displayedSubjects: displayedSubjects))
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListSubjects/ListSubjectsRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSubjectsRouter.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | protocol ListSubjectsRouterProtocol {
9 | func navigateToListCourses()
10 | }
11 |
12 | class ListSubjectsRouter: ListSubjectsRouterProtocol {
13 |
14 | fileprivate static let ShowListCoursesSegueId = "ShowListCoursesScene"
15 |
16 | weak var viewController: ListSubjectsViewController!
17 |
18 | // MARK: Navigation
19 |
20 | func navigateToListCourses() {
21 | // NOTE: Teach the router how to navigate to another scene. Some examples follow:
22 |
23 | // 1. Trigger a storyboard segue
24 | viewController.performSegue(withIdentifier: ListSubjectsRouter.ShowListCoursesSegueId, sender: nil)
25 |
26 | // 2. Present another view controller programmatically
27 | // viewController.presentViewController(someWhereViewController, animated: true, completion: nil)
28 |
29 | // 3. Ask the navigation controller to push another view controller onto the stack
30 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
31 |
32 | // 4. Present a view controller from a different storyboard
33 | // let storyboard = UIStoryboard(name: "OtherThanMain", bundle: nil)
34 | // let someWhereViewController = storyboard.instantiateInitialViewController() as! SomeWhereViewController
35 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
36 | }
37 |
38 | // MARK: Communication
39 |
40 | func passDataToNextScene(_ segue: UIStoryboardSegue) {
41 | // NOTE: Teach the router which scenes it can communicate with
42 |
43 | if segue.identifier == ListSubjectsRouter.ShowListCoursesSegueId {
44 | passDataToListCoursesScene(segue)
45 | }
46 | }
47 |
48 | func passDataToListCoursesScene(_ segue: UIStoryboardSegue) {
49 | if let selectedIndexPath = viewController.tableView.indexPathForSelectedRow {
50 | if let selectedSubject = viewController.output.subjects?[(selectedIndexPath as NSIndexPath).row] {
51 | // swiftlint:disable:next force_cast
52 | let listCoursesViewController = segue.destination as! ListCoursesViewController
53 | listCoursesViewController.output.subject = selectedSubject
54 | }
55 | }
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListSubjects/ListSubjectsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSubjectsViewController.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | protocol ListSubjectsViewProtocol: class {
9 | func displayFetchedSubjects(_ viewModel: ListSubjects.ViewModel)
10 | }
11 |
12 | class ListSubjectsViewController: UITableViewController,
13 | ListSubjectsViewProtocol {
14 |
15 | var output: ListSubjectsInteractorInput!
16 | var router: ListSubjectsRouter!
17 | var displayedSubjects: [ListSubjects.ViewModel.DisplayedSubject] = []
18 |
19 | // MARK: Object lifecycle
20 |
21 | override func awakeFromNib() {
22 | super.awakeFromNib()
23 | ListSubjectsConfigurator.sharedInstance.configure(self)
24 | }
25 |
26 | // MARK: View lifecycle
27 |
28 | override func viewDidLoad() {
29 | super.viewDidLoad()
30 | fetchSubjectsOnLoad()
31 | }
32 |
33 | // MARK: Event handling
34 |
35 | func fetchSubjectsOnLoad() {
36 | let request = ListSubjects.Request()
37 | output.fetchSubjects(request)
38 | }
39 |
40 | // MARK: Display logic
41 |
42 | func displayFetchedSubjects(_ viewModel: ListSubjects.ViewModel) {
43 | displayedSubjects = viewModel.displayedSubjects
44 | tableView.reloadData()
45 | }
46 |
47 | // MARK: - UITableViewDelegate
48 |
49 | override func tableView(_ tableView: UITableView,
50 | didSelectRowAt indexPath: IndexPath) {
51 | router.navigateToListCourses()
52 | }
53 |
54 | // MARK: - UITableViewDataSource
55 |
56 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
57 | return displayedSubjects.count
58 | }
59 |
60 | override func tableView(_ tableView: UITableView,
61 | cellForRowAt indexPath: IndexPath) -> UITableViewCell {
62 | let cell = tableView.dequeueReusableCell(withIdentifier: "subjectCell",
63 | for: indexPath)
64 |
65 | let displayedSubject = displayedSubjects[(indexPath as NSIndexPath).row]
66 | cell.textLabel?.text = "\(displayedSubject.code) - \(displayedSubject.name)"
67 |
68 | return cell
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ListSubjects/ListSubjectsWorker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSubjectsWorker.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ListSubjectsWorker: ListSubjectsWorkerProtocol {
9 |
10 | let subjectsWorker: SubjectsWorker = SubjectsWorker(subjectsStore: SubjectsRealmStore())
11 |
12 | // MARK: Business Logic
13 |
14 | func fetchSubjects(_ completionHandler: @escaping (_ subjects: [Subject]) -> Void) {
15 | subjectsWorker.fetchSubjects { (subjects) in
16 | completionHandler(subjects)
17 | }
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ShowOptions/ShowOptionsConfigurator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowOptionsConfigurator.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | // MARK: Connect View, Interactor, and Presenter
9 |
10 | extension ShowOptionsViewController {
11 |
12 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
13 | router.passDataToNextScene(segue)
14 | }
15 |
16 | }
17 |
18 | class ShowOptionsConfigurator {
19 |
20 | // MARK: Object lifecycle
21 |
22 | static let sharedInstance: ShowOptionsConfigurator = {
23 | let instance = ShowOptionsConfigurator()
24 | return instance
25 | }()
26 |
27 | // MARK: Configuration
28 |
29 | func configure(_ viewController: ShowOptionsViewController) {
30 | let router = ShowOptionsRouter()
31 | router.viewController = viewController
32 |
33 | let presenter = ShowOptionsPresenter()
34 | presenter.output = viewController
35 |
36 | let interactor = ShowOptionsInteractor()
37 | interactor.output = presenter
38 |
39 | viewController.output = interactor
40 | viewController.router = router
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ShowOptions/ShowOptionsInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowOptionsInteractor.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | protocol ShowOptionsInteractorInput {
9 | func doSomething(_ request: ShowOptions.Request)
10 | }
11 |
12 | protocol ShowOptionsInteractorOutput {
13 | func presentSomething(_ response: ShowOptions.Response)
14 | }
15 |
16 | protocol ShowOptionsWorkerProtocol {
17 | func doSomeWork()
18 | }
19 |
20 | class ShowOptionsInteractor: ShowOptionsInteractorInput {
21 | var output: ShowOptionsInteractorOutput!
22 | var worker: ShowOptionsWorkerProtocol! = ShowOptionsWorker()
23 |
24 | // MARK: Business logic
25 |
26 | func doSomething(_ request: ShowOptions.Request) {
27 | // NOTE: Create some Worker to do the work
28 |
29 | worker.doSomeWork()
30 |
31 | // NOTE: Pass the result to the Presenter
32 |
33 | let response = ShowOptions.Response()
34 | output.presentSomething(response)
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ShowOptions/ShowOptionsModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowOptionsModels.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | struct ShowOptions {
9 |
10 | struct Request {
11 | }
12 |
13 | struct Response {
14 | }
15 |
16 | struct ViewModel {
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ShowOptions/ShowOptionsPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowOptionsPresenter.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ShowOptionsPresenter: ShowOptionsInteractorOutput {
9 | weak var output: ShowOptionsViewInput!
10 |
11 | // MARK: Presentation logic
12 |
13 | func presentSomething(_ response: ShowOptions.Response) {
14 | // NOTE: Format the response from the Interactor and pass the result back to the View Controller
15 |
16 | let viewModel = ShowOptions.ViewModel()
17 | output.displaySomething(viewModel)
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ShowOptions/ShowOptionsRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowOptionsRouter.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | protocol ShowOptionsRouterInput {
9 | func navigateToSomewhere()
10 | }
11 |
12 | class ShowOptionsRouter: ShowOptionsRouterInput {
13 | weak var viewController: ShowOptionsViewController!
14 |
15 | // MARK: Navigation
16 |
17 | func navigateToSomewhere() {
18 | // NOTE: Teach the router how to navigate to another scene. Some examples follow:
19 |
20 | // 1. Trigger a storyboard segue
21 | // viewController.performSegueWithIdentifier("ShowSomewhereScene", sender: nil)
22 |
23 | // 2. Present another view controller programmatically
24 | // viewController.presentViewController(someWhereViewController, animated: true, completion: nil)
25 |
26 | // 3. Ask the navigation controller to push another view controller onto the stack
27 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
28 |
29 | // 4. Present a view controller from a different storyboard
30 | // let storyboard = UIStoryboard(name: "OtherThanMain", bundle: nil)
31 | // let someWhereViewController = storyboard.instantiateInitialViewController() as! SomeWhereViewController
32 | // viewController.navigationController?.pushViewController(someWhereViewController, animated: true)
33 | }
34 |
35 | // MARK: Communication
36 |
37 | func passDataToNextScene(_ segue: UIStoryboardSegue) {
38 | // NOTE: Teach the router which scenes it can communicate with
39 |
40 | if segue.identifier == "ShowSomewhereScene" {
41 | passDataToSomewhereScene(segue)
42 | }
43 | }
44 |
45 | func passDataToSomewhereScene(_ segue: UIStoryboardSegue) {
46 | // NOTE: Teach the router how to pass data to the next scene
47 |
48 | // let someWhereViewController = segue.destinationViewController as! SomeWhereViewController
49 | // someWhereViewController.output.name = viewController.output.name
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ShowOptions/ShowOptionsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowOptionsViewController.swift
3 | // FIUBA
4 | //
5 |
6 | import UIKit
7 |
8 | protocol ShowOptionsViewInput: class {
9 | func displaySomething(_ viewModel: ShowOptions.ViewModel)
10 | }
11 |
12 | class ShowOptionsViewController: UIViewController, ShowOptionsViewInput {
13 |
14 | var output: ShowOptionsInteractorInput!
15 | var router: ShowOptionsRouter!
16 |
17 | // MARK: Object lifecycle
18 |
19 | override func awakeFromNib() {
20 | super.awakeFromNib()
21 | ShowOptionsConfigurator.sharedInstance.configure(self)
22 | }
23 |
24 | // MARK: View lifecycle
25 |
26 | override func viewDidLoad() {
27 | super.viewDidLoad()
28 | doSomethingOnLoad()
29 | }
30 |
31 | // MARK: Event handling
32 |
33 | func doSomethingOnLoad() {
34 | // NOTE: Ask the Interactor to do some work
35 |
36 | let request = ShowOptions.Request()
37 | output.doSomething(request)
38 | }
39 |
40 | // MARK: Display logic
41 |
42 | func displaySomething(_ viewModel: ShowOptions.ViewModel) {
43 | // NOTE: Display the result from the Presenter
44 |
45 | // nameTextField.text = viewModel.name
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/ios/FIUBA/Scenes/ShowOptions/ShowOptionsWorker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowOptionsWorker.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class ShowOptionsWorker: ShowOptionsWorkerProtocol {
9 |
10 | // MARK: Business Logic
11 |
12 | func doSomeWork() {
13 | // NOTE: Do the work
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/ios/FIUBA/Services/CoursesJsonStore.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CoursesJsonStore.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | typealias Payload = [String: AnyObject]
9 |
10 | class CoursesJsonStore: CoursesStoreProtocol {
11 |
12 | func fetchCourses(_ completionHandler: @escaping CoursesStoreFetchCoursesCompletionHandler) {
13 | DataManager.loadDataFromJsonFile("courses", success: { (data) in
14 | var json: Payload!
15 | do {
16 | json = try JSONSerialization.jsonObject(with: data,
17 | options: JSONSerialization.ReadingOptions()) as? Payload
18 | guard let coursesArray = json["courses"] as? [Payload] else {
19 | completionHandler(CoursesStoreResult.failure(error: CoursesStoreError.cannotFetch("Cannot fetch courses")))
20 | return
21 | }
22 | let courses = coursesArray.map({ (dict) -> Course in
23 | let course = Course(id: dict["id"] as? String,
24 | subjectId: dict["subjectId"] as? String,
25 | number: dict["number"] as? Int,
26 | teachers: dict["teachers"] as? String,
27 | vacancies: dict["vacancy"] as? Int,
28 | enrolled: false)
29 | return course
30 | })
31 | completionHandler(CoursesStoreResult.success(result: courses))
32 | } catch {
33 | completionHandler(CoursesStoreResult.failure(error: CoursesStoreError.cannotFetch("Cannot fetch courses")))
34 | }
35 |
36 | })
37 | }
38 |
39 | func fetchCoursesBySubject(_ subject: Subject, completionHandler: CoursesStoreFetchCoursesCompletionHandler) {
40 |
41 | }
42 |
43 | func fetchEnrolledCourses(_ completionHandler: CoursesStoreFetchCoursesCompletionHandler) {
44 |
45 | }
46 |
47 | func fetchCourse(_ id: String, completionHandler: CoursesStoreFetchCourseCompletionHandler) {
48 |
49 | }
50 |
51 | func createCourse(_ courseToCreate: Course, completionHandler: CoursesStoreCreateCourseCompletionHandler) {
52 |
53 | }
54 |
55 | func createCourses(_ coursesToCreate: [Course], completionHandler: CoursesStoreCreateCoursesCompletionHandler) {
56 |
57 | }
58 |
59 | func updateCourse(_ courseToUpdate: Course, completionHandler: CoursesStoreUpdateCourseCompletionHandler) {
60 |
61 | }
62 |
63 | func deleteCourse(_ id: String, completionHandler: CoursesStoreDeleteCourseCompletionHandler) {
64 |
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/ios/FIUBA/Services/Json/DataManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataManager.swift
3 | // TopApps
4 | //
5 | // Created by Attila on 2015. 11. 10..
6 | // Copyright © 2015. -. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | open class DataManager {
12 |
13 | open class func loadDataFromJsonFile(_ fileName: String, success: @escaping ((_ data: Data) -> Void)) {
14 | DispatchQueue.global(qos: .utility).async {
15 | let filePath = Bundle.main.path(forResource: fileName, ofType:"json")
16 | // swiftlint:disable:next force_try
17 | let data = try! Data(contentsOf: URL(fileURLWithPath: filePath!),
18 | options: NSData.ReadingOptions.uncached)
19 | success(data)
20 | }
21 | }
22 |
23 | open class func loadDataFromURL(_ url: URL, completion:@escaping (_ data: Data?, _ error: NSError?) -> Void) {
24 | let session = URLSession.shared
25 |
26 | let loadDataTask = session.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
27 | if let responseError = error {
28 | completion(nil, responseError as NSError?)
29 | } else if let httpResponse = response as? HTTPURLResponse {
30 | if httpResponse.statusCode != 200 {
31 | let statusError = NSError(domain: "com.raywenderlich",
32 | code: httpResponse.statusCode,
33 | userInfo: [NSLocalizedDescriptionKey : "HTTP status code has unexpected value."])
34 | completion(nil, statusError)
35 | } else {
36 | completion(data, nil)
37 | }
38 | }
39 | })
40 |
41 | loadDataTask.resume()
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/ios/FIUBA/Services/Realm/CourseRLM.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CourseRLM.swift
3 | // FIUBA
4 | //
5 |
6 | import RealmSwift
7 |
8 | class CourseRLM: Object {
9 | dynamic var id: String = ""
10 | dynamic var subjectId: String = ""
11 | dynamic var number: Int = 0
12 | dynamic var teachers: String = ""
13 | dynamic var vacancies: Int = 0
14 | dynamic var enrolled: Bool = false
15 |
16 | override static func primaryKey() -> String? {
17 | return "id"
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/ios/FIUBA/Services/Realm/SubjectRLM.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SubjectRLM.swift
3 | // FIUBA
4 | //
5 |
6 | import RealmSwift
7 |
8 | class SubjectRLM: Object {
9 | dynamic var id: String = ""
10 | dynamic var code: String = ""
11 | dynamic var name: String = ""
12 |
13 | override static func primaryKey() -> String? {
14 | return "id"
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/ios/FIUBA/Services/SubjectsJsonStore.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SubjectsJsonStore.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class SubjectsJsonStore: SubjectsStoreProtocol {
9 |
10 | // MARK: CRUD operations - Generic enum result type
11 |
12 | func fetchSubjects(_ completionHandler: @escaping SubjectsStoreFetchSubjectsCompletionHandler) {
13 | DataManager.loadDataFromJsonFile("subjects", success: { (data) in
14 | var json: Payload!
15 | do {
16 | json = try JSONSerialization.jsonObject(with: data,
17 | options: JSONSerialization.ReadingOptions()) as? Payload
18 | guard let subjectsArray = json["subjects"] as? [Payload] else {
19 | completionHandler(SubjectsStoreResult.failure(error: SubjectsStoreError.cannotFetch("Cannot fetch subjects")))
20 | return
21 | }
22 | let subjects = subjectsArray.map({ (dict) -> Subject in
23 | let subject = Subject(id: dict["id"] as? String,
24 | code: dict["code"] as? String,
25 | name: dict["name"] as? String)
26 | return subject
27 | })
28 | completionHandler(SubjectsStoreResult.success(result: subjects))
29 | } catch {
30 | completionHandler(SubjectsStoreResult.failure(error: SubjectsStoreError.cannotFetch("Cannot fetch subjects")))
31 | }
32 |
33 | })
34 | }
35 |
36 | func fetchSubject(_ id: String, completionHandler: SubjectsStoreFetchSubjectCompletionHandler) {
37 |
38 | }
39 |
40 | func createSubject(_ subjectToCreate: Subject, completionHandler: SubjectsStoreCreateSubjectCompletionHandler) {
41 |
42 | }
43 |
44 | func createSubjects(_ subjectsToCreate: [Subject], completionHandler: SubjectsStoreCreateSubjectsCompletionHandler) {
45 |
46 | }
47 |
48 | func updateSubject(_ subjectToUpdate: Subject, completionHandler: SubjectsStoreUpdateSubjectCompletionHandler) {
49 |
50 | }
51 |
52 | func deleteSubject(_ id: String, completionHandler: SubjectsStoreDeleteSubjectCompletionHandler) {
53 |
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/ios/FIUBA/Services/SubjectsRealmStore.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SubjectsRealmStore.swift
3 | // FIUBA
4 | //
5 |
6 | import RealmSwift
7 |
8 | class SubjectsRealmStore: SubjectsStoreProtocol {
9 |
10 | func fetchSubjects(_ completionHandler: @escaping SubjectsStoreFetchSubjectsCompletionHandler) {
11 | guard let realm = realm() else {
12 | completionHandler(SubjectsStoreResult.failure(error: SubjectsStoreError.cannotFetch("No se pudo instanciar Realm")))
13 | return
14 | }
15 |
16 | let rlmSubjects = realm.objects(SubjectRLM.self)
17 | let subjects: [Subject] = rlmSubjects.map { (rlmSubject) -> Subject in
18 | return Subject(id: rlmSubject.id,
19 | code: rlmSubject.code,
20 | name: rlmSubject.name)
21 | }
22 | completionHandler(SubjectsStoreResult.success(result: subjects))
23 | }
24 |
25 | func fetchSubject(_ id: String, completionHandler: SubjectsStoreFetchSubjectCompletionHandler) {
26 |
27 | }
28 |
29 | func createSubject(_ subjectToCreate: Subject, completionHandler: SubjectsStoreCreateSubjectCompletionHandler) {
30 |
31 | }
32 |
33 | func createSubjects(_ subjects: [Subject], completionHandler: SubjectsStoreCreateSubjectsCompletionHandler) {
34 | guard let realm = realm() else {
35 | completionHandler(SubjectsStoreResult.failure(error: SubjectsStoreError.cannotCreate("No se pudo instanciar Realm")))
36 | return
37 | }
38 |
39 | let rlmSubjects: [SubjectRLM] = subjects.map { (subject) -> SubjectRLM in
40 | let rlmSubject = SubjectRLM()
41 | rlmSubject.id = subject.id ?? ""
42 | rlmSubject.code = subject.code ?? ""
43 | rlmSubject.name = subject.name ?? ""
44 | return rlmSubject
45 | }
46 | do {
47 | try realm.write {
48 | for subject in rlmSubjects {
49 | realm.add(subject)
50 | }
51 | }
52 | } catch {
53 | completionHandler(SubjectsStoreResult.failure(error: SubjectsStoreError.cannotCreate("No se pudo escribir en Realm")))
54 | return
55 | }
56 | completionHandler(SubjectsStoreResult.success(result: ()))
57 | }
58 |
59 | func updateSubject(_ subjectToUpdate: Subject, completionHandler: SubjectsStoreUpdateSubjectCompletionHandler) {
60 |
61 | }
62 |
63 | func deleteSubject(_ id: String, completionHandler: SubjectsStoreDeleteSubjectCompletionHandler) {
64 |
65 | }
66 |
67 | // MARK: - Auxiliars
68 |
69 | fileprivate func realm() -> Realm? {
70 | do {
71 | return try Realm()
72 | } catch {
73 | return nil
74 | }
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/ios/FIUBA/Workers/SubjectsWorker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SubjectsWorker.swift
3 | // FIUBA
4 | //
5 |
6 | import Foundation
7 |
8 | class SubjectsWorker {
9 |
10 | var subjectsStore: SubjectsStoreProtocol
11 |
12 | init(subjectsStore: SubjectsStoreProtocol) {
13 | self.subjectsStore = subjectsStore
14 | }
15 |
16 | func fetchSubjects(_ completionHandler: @escaping (_ subjects: [Subject]) -> Void) {
17 | subjectsStore.fetchSubjects { (result) in
18 | switch result {
19 | case .success(let subjects):
20 | completionHandler(subjects)
21 | case .failure( _):
22 | completionHandler([])
23 | }
24 | }
25 | }
26 |
27 | func createSubjects(_ subjectsToCreate: [Subject]) {
28 | subjectsStore.createSubjects(subjectsToCreate) { (result) in
29 | }
30 | }
31 |
32 | }
33 |
34 | protocol SubjectsStoreProtocol {
35 |
36 | // MARK: CRUD operations - Generic enum result type
37 |
38 | func fetchSubjects(_ completionHandler: @escaping SubjectsStoreFetchSubjectsCompletionHandler)
39 | func fetchSubject(_ id: String, completionHandler: SubjectsStoreFetchSubjectCompletionHandler)
40 | func createSubject(_ subjectToCreate: Subject, completionHandler: SubjectsStoreCreateSubjectCompletionHandler)
41 | func createSubjects(_ subjectsToCreate: [Subject], completionHandler: SubjectsStoreCreateSubjectsCompletionHandler)
42 | func updateSubject(_ subjectToUpdate: Subject, completionHandler: SubjectsStoreUpdateSubjectCompletionHandler)
43 | func deleteSubject(_ id: String, completionHandler: SubjectsStoreDeleteSubjectCompletionHandler)
44 |
45 | }
46 |
47 | // MARK: - Subjects store CRUD operation results
48 |
49 | typealias SubjectsStoreFetchSubjectsCompletionHandler = (_ result: SubjectsStoreResult<[Subject]>) -> Void
50 | typealias SubjectsStoreFetchSubjectCompletionHandler = (_ result: SubjectsStoreResult) -> Void
51 | typealias SubjectsStoreCreateSubjectCompletionHandler = (_ result: SubjectsStoreResult) -> Void
52 | typealias SubjectsStoreCreateSubjectsCompletionHandler = (_ result: SubjectsStoreResult) -> Void
53 | typealias SubjectsStoreUpdateSubjectCompletionHandler = (_ result: SubjectsStoreResult) -> Void
54 | typealias SubjectsStoreDeleteSubjectCompletionHandler = (_ result: SubjectsStoreResult) -> Void
55 |
56 | enum SubjectsStoreResult {
57 | case success(result: U)
58 | case failure(error: SubjectsStoreError)
59 | }
60 |
61 | // MARK: - Subjects store CRUD operation errors
62 |
63 | enum SubjectsStoreError: Equatable, Error {
64 | case cannotFetch(String)
65 | case cannotCreate(String)
66 | case cannotUpdate(String)
67 | case cannotDelete(String)
68 | }
69 |
70 | func==(lhs: SubjectsStoreError, rhs: SubjectsStoreError) -> Bool {
71 | switch (lhs, rhs) {
72 | case (.cannotFetch(let a), .cannotFetch(let b)) where a == b: return true
73 | case (.cannotCreate(let a), .cannotCreate(let b)) where a == b: return true
74 | case (.cannotUpdate(let a), .cannotUpdate(let b)) where a == b: return true
75 | case (.cannotDelete(let a), .cannotDelete(let b)) where a == b: return true
76 | default: return false
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/ios/FIUBATests/FIUBATests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FIUBATests.swift
3 | // FIUBATests
4 | //
5 |
6 | import XCTest
7 | @testable import FIUBA
8 |
9 | class FIUBATests: XCTestCase {
10 |
11 | override func setUp() {
12 | super.setUp()
13 | // Put setup code here.
14 | // This method is called before the invocation of each test method in the class.
15 | }
16 |
17 | override func tearDown() {
18 | // Put teardown code here.
19 | // This method is called after the invocation of each test method in the class.
20 | super.tearDown()
21 | }
22 |
23 | func testExample() {
24 | // This is an example of a functional test case.
25 | // Use XCTAssert and related functions to verify your tests produce the correct results.
26 | }
27 |
28 | func testPerformanceExample() {
29 | // This is an example of a performance test case.
30 | self.measure {
31 | // Put the code you want to measure the time of here.
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/ios/FIUBATests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ios/FIUBATests/ListCoursesInteractorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListCoursesInteractorTests.swift
3 | // FIUBA
4 | //
5 | // Created by Ezequiel Pérez Dittler on 7/6/16.
6 | // Copyright © 2016 FIUBA. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import FIUBA
11 |
12 | class ListCoursesWorkerMock: ListCoursesWorkerProtocol {
13 | var enrollCount: Int = 0
14 |
15 | func fetchCoursesBySubject(_ subject: Subject, completionHandler: (_ courses: [Course]) -> Void) {
16 |
17 | }
18 |
19 | func fetchEnrolledCourses(_ completionHandler: (_ courses: [Course]) -> Void) {
20 | var courses: [Course] = []
21 | for _ in 0..
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '9.0'
2 |
3 | target 'FIUBA' do
4 | use_frameworks!
5 |
6 | # Pods for FIUBA
7 | pod 'RealmSwift'
8 |
9 | target 'FIUBATests' do
10 | inherit! :search_paths
11 | # Pods for testing
12 | end
13 |
14 | target 'FIUBAUITests' do
15 | inherit! :search_paths
16 | # Pods for testing
17 | end
18 |
19 | end
20 |
21 | post_install do |installer|
22 | installer.pods_project.targets.each do |target|
23 | target.build_configurations.each do |config|
24 | config.build_settings['SWIFT_VERSION'] = '3.0'
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Realm (2.0.2):
3 | - Realm/Headers (= 2.0.2)
4 | - Realm/Headers (2.0.2)
5 | - RealmSwift (2.0.2):
6 | - Realm (= 2.0.2)
7 |
8 | DEPENDENCIES:
9 | - RealmSwift
10 |
11 | SPEC CHECKSUMS:
12 | Realm: 0f5a194af0b7e6158b83db41b4ee1a00be7ddf1a
13 | RealmSwift: 0eb5070d851cba7c66e841ca756d83609dc78bc8
14 |
15 | PODFILE CHECKSUM: c111236cb73c518f45e2f211b0cf5cfecc931f77
16 |
17 | COCOAPODS: 1.0.1
18 |
--------------------------------------------------------------------------------
/resources/BalsamiqMockup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/BalsamiqMockup.png
--------------------------------------------------------------------------------
/resources/clean1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean1.png
--------------------------------------------------------------------------------
/resources/clean10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean10.png
--------------------------------------------------------------------------------
/resources/clean11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean11.png
--------------------------------------------------------------------------------
/resources/clean12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean12.png
--------------------------------------------------------------------------------
/resources/clean13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean13.png
--------------------------------------------------------------------------------
/resources/clean2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean2.png
--------------------------------------------------------------------------------
/resources/clean3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean3.png
--------------------------------------------------------------------------------
/resources/clean4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean4.png
--------------------------------------------------------------------------------
/resources/clean5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean5.png
--------------------------------------------------------------------------------
/resources/clean6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean6.png
--------------------------------------------------------------------------------
/resources/clean7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean7.png
--------------------------------------------------------------------------------
/resources/clean8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean8.png
--------------------------------------------------------------------------------
/resources/clean9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edittler/clean-architecture/640cb0fea9edbed115c4d58714a35ea753f11693/resources/clean9.png
--------------------------------------------------------------------------------