Skip to content

Commit ea30758

Browse files
authored
Feat/form brown bear (#478)
1 parent a20f779 commit ea30758

23 files changed

+1097
-24
lines changed

app/src/main/java/org/bspb/smartbirds/pro/backend/SmartBirdsApi.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ public interface SmartBirdsApi {
100100
@POST("bats")
101101
Call<UploadFormResponse> createBat(@Body JsonObject request);
102102

103+
@POST("bears")
104+
Call<UploadFormResponse> createBear(@Body JsonObject request);
105+
103106
@DELETE("user/{id}")
104107
Call<BaseResponse> deleteUser(@Path("id") long id);
105108
}

app/src/main/java/org/bspb/smartbirds/pro/enums/EntryType.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.bspb.smartbirds.pro.R;
1313
import org.bspb.smartbirds.pro.forms.convert.BatsConverter;
14+
import org.bspb.smartbirds.pro.forms.convert.BearsConverter;
1415
import org.bspb.smartbirds.pro.forms.convert.BirdsConverter;
1516
import org.bspb.smartbirds.pro.forms.convert.BirdsMigrationsConverter;
1617
import org.bspb.smartbirds.pro.forms.convert.CbmConverter;
@@ -25,6 +26,7 @@
2526
import org.bspb.smartbirds.pro.forms.convert.PylonsConverter;
2627
import org.bspb.smartbirds.pro.forms.convert.ThreatsConverter;
2728
import org.bspb.smartbirds.pro.forms.upload.BatsUploader;
29+
import org.bspb.smartbirds.pro.forms.upload.BearsUploader;
2830
import org.bspb.smartbirds.pro.forms.upload.BirdsMigrationsUploader;
2931
import org.bspb.smartbirds.pro.forms.upload.BirdsUploader;
3032
import org.bspb.smartbirds.pro.forms.upload.CbmUploader;
@@ -40,6 +42,7 @@
4042
import org.bspb.smartbirds.pro.forms.upload.Uploader;
4143
import org.bspb.smartbirds.pro.ui.fragment.BaseEntryFragment;
4244
import org.bspb.smartbirds.pro.ui.fragment.NewBatsEntryFormFragment;
45+
import org.bspb.smartbirds.pro.ui.fragment.NewBearsEntryFormFragment;
4346
import org.bspb.smartbirds.pro.ui.fragment.NewBirdsEntryFormFragment;
4447
import org.bspb.smartbirds.pro.ui.fragment.NewBirdsMigrationsEntryFormFragment;
4548
import org.bspb.smartbirds.pro.ui.fragment.NewCbmEntryFormFragment;
@@ -66,14 +69,15 @@ public enum EntryType {
6669
CICONIA(new NewCiconiaEntryFormFragment.Builder(), R.string.entry_type_ciconia, R.id.action_form_type_ciconia, "form_ciconia.csv", CiconiaConverter.class, CiconiaUploader.class, true),
6770
HERPTILE(new NewHerptileEntryFormFragment.Builder(), R.string.entry_type_herptile, R.id.action_form_type_herptile, "form_herptile.csv", HerptileConverter.class, HerptileUploader.class, true),
6871
MAMMAL(new NewMammalEntryFormFragment.Builder(), R.string.entry_type_mammal, R.id.action_form_type_mammal, "form_mammal.csv", MammalConverter.class, MammalUploader.class, true),
72+
BEARS(new NewBearsEntryFormFragment.Builder(), R.string.entry_type_bears, R.id.action_form_type_bears, "form_bears.csv", BearsConverter.class, BearsUploader.class, true),
6973
INVERTEBRATES(new NewInvertebratesEntryFormFragment.Builder(), R.string.entry_type_invertebrates, R.id.action_form_type_invertebrates, "form_invertebrates.csv", InvertebratesConverter.class, InvertebratesUploader.class, true),
7074
PLANTS(new NewPlantsEntryFormFragment.Builder(), R.string.entry_type_plants, R.id.action_form_type_plants, "form_plants.csv", PlantsConverter.class, PlantsUploader.class, true),
7175
THREATS(new NewThreatsEntryFormFragment.Builder(), R.string.entry_type_threats, R.id.action_form_type_threats, "form_threats.csv", ThreatsConverter.class, ThreatsUploader.class, true),
7276
PYLONS(new NewPylonsEntryFormFragment.Builder(), R.string.entry_type_pylons, R.id.action_form_type_pylons, "form_pylons.csv", PylonsConverter.class, PylonsUploader.class, true),
7377
PYLONS_CASUALTIES(new NewPylonsCasualtiesEntryFormFragment.Builder(), R.string.entry_type_pylons_casualties, R.id.action_form_type_pylons_casualties, "form_pylons_casualties.csv", PylonsCasualtiesConverter.class, PylonsCasualtiesUploader.class, true),
7478
BIRDS_MIGRATIONS(new NewBirdsMigrationsEntryFormFragment.Builder(), R.string.entry_type_birds_migrations, R.id.action_form_type_birds_migrations, "form_birds_migrations.csv", BirdsMigrationsConverter.class, BirdsMigrationsUploader.class, true),
7579
FISH(new NewFishesEntryFormFragment.Builder(), R.string.entry_type_fish, R.id.action_form_type_fish, "form_fish.csv", FishesConverter.class, FishesUploader.class, true),
76-
BATS(new NewBatsEntryFormFragment.Builder(), R.string.entry_type_bats, R.id.action_form_type_bats, "form_bats.csv", BatsConverter.class, BatsUploader.class, true),
80+
BATS(new NewBatsEntryFormFragment.Builder(), R.string.entry_type_bats, R.id.action_form_type_bats, "form_bats.csv", BatsConverter.class, BatsUploader.class, true)
7781
// prevent auto-formatting
7882
;
7983

@@ -84,6 +88,7 @@ public enum EntryType {
8488
R.id.action_form_type_humid,
8589
R.id.action_form_type_herptile,
8690
R.id.action_form_type_mammal,
91+
R.id.action_form_type_bears,
8792
R.id.action_form_type_invertebrates,
8893
R.id.action_form_type_plants,
8994
R.id.action_form_type_threats,

app/src/main/java/org/bspb/smartbirds/pro/ui/MonitoringActivity.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,23 @@ public boolean onOptionsItemSelected(MenuItem item) {
427427
setZoomFree(item);
428428
return true;
429429
}
430-
if ((((((((((((((itemId == R.id.action_form_type_birds) || (itemId == R.id.action_form_type_cbm)) || (itemId == R.id.action_form_type_ciconia)) || (itemId == R.id.action_form_type_humid)) || (itemId == R.id.action_form_type_herptile)) || (itemId == R.id.action_form_type_mammal)) || (itemId == R.id.action_form_type_invertebrates)) || (itemId == R.id.action_form_type_plants)) || (itemId == R.id.action_form_type_threats)) || (itemId == R.id.action_form_type_pylons)) || (itemId == R.id.action_form_type_pylons_casualties)) || (itemId == R.id.action_form_type_birds_migrations)) || (itemId == R.id.action_form_type_fish)) || (itemId == R.id.action_form_type_bats)) {
430+
if (
431+
(itemId == R.id.action_form_type_birds) ||
432+
(itemId == R.id.action_form_type_cbm) ||
433+
(itemId == R.id.action_form_type_ciconia) ||
434+
(itemId == R.id.action_form_type_humid) ||
435+
(itemId == R.id.action_form_type_herptile) ||
436+
(itemId == R.id.action_form_type_mammal) ||
437+
(itemId == R.id.action_form_type_invertebrates) ||
438+
(itemId == R.id.action_form_type_plants) ||
439+
(itemId == R.id.action_form_type_threats) ||
440+
(itemId == R.id.action_form_type_pylons) ||
441+
(itemId == R.id.action_form_type_pylons_casualties) ||
442+
(itemId == R.id.action_form_type_birds_migrations) ||
443+
(itemId == R.id.action_form_type_fish) ||
444+
(itemId == R.id.action_form_type_bats) ||
445+
(itemId == R.id.action_form_type_bears)
446+
) {
431447
setFormType(item);
432448
return true;
433449
}

app/src/main/java/org/bspb/smartbirds/pro/ui/partial/MonitoringEntryListRowPartialView.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ public void bind(MonitoringEntry entry) {
178178
speciesView.setText(entry.data.get(context.getString(R.string.tag_species_scientific_name)));
179179
countView.setText(entry.data.get(context.getString(R.string.tag_count)));
180180
break;
181+
case BEARS:
182+
typeView.setText(R.string.entry_type_bears);
183+
speciesView.setText(entry.data.get(context.getString(R.string.tag_species_scientific_name)));
184+
countView.setText(entry.data.get(context.getString(R.string.tag_count)));
185+
break;
186+
181187
}
182188
}
183189

app/src/main/java/org/bspb/smartbirds/pro/ui/utils/FormUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import org.bspb.smartbirds.pro.SmartBirdsApplication;
1111
import org.bspb.smartbirds.pro.ui.exception.ViewValidationException;
12+
import org.bspb.smartbirds.pro.ui.views.SupportReadOnly;
1213
import org.bspb.smartbirds.pro.ui.views.SupportRequiredView;
1314
import org.bspb.smartbirds.pro.ui.views.SupportStorage;
1415

@@ -120,7 +121,10 @@ public boolean validateFields() {
120121
}
121122

122123
public static void serialize(Map<String, String> storage, String field, View view) {
123-
if (!view.isEnabled()) {
124+
// Check if view is readonly - readonly views should persist even when disabled
125+
boolean isReadOnly = (view instanceof SupportReadOnly) && ((SupportReadOnly) view).isReadOnly();
126+
127+
if (!view.isEnabled() && !isReadOnly) {
124128
storage.put(field, "");
125129
return;
126130
}

app/src/main/java/org/bspb/smartbirds/pro/ui/views/SingleChoiceFormInput.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@
4646
/**
4747
* Created by groupsky on 14-10-10.
4848
*/
49-
public class SingleChoiceFormInput extends TextViewFormInput implements SupportStorage {
49+
public class SingleChoiceFormInput extends TextViewFormInput implements SupportStorage, SupportReadOnly {
5050

5151
private CharSequence key;
52+
private boolean mReadOnly = false;
5253

5354
NomenclaturesManager nomenclatures = NomenclaturesManager.Companion.getInstance();
5455

@@ -77,10 +78,16 @@ public SingleChoiceFormInput(Context context, AttributeSet attrs, int defStyle)
7778
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SingleChoiceFormInput, defStyle, 0);
7879
try {
7980
key = a.getText(R.styleable.SingleChoiceFormInput_entriesType);
81+
boolean readonly = a.getBoolean(R.styleable.SingleChoiceFormInput_readonly, false);
8082
SmartArrayAdapter<NomenclatureItem> adapter = new SmartArrayAdapter<>(context,
8183
R.layout.item_dialog_single_choice, new ArrayList<NomenclatureItem>());
8284
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
8385
setAdapter(adapter);
86+
87+
// Apply readonly state if specified in XML
88+
if (readonly) {
89+
setReadOnly(true);
90+
}
8491
} finally {
8592
a.recycle();
8693
}
@@ -208,8 +215,31 @@ public void setSelection(NomenclatureItem item) {
208215
if (onSelectionChangeListener != null) onSelectionChangeListener.onSelectionChange(this);
209216
}
210217

218+
@Override
219+
public void setReadOnly(boolean readOnly) {
220+
mReadOnly = readOnly;
221+
if (readOnly) {
222+
// Prevent interaction with the view
223+
setFocusable(false);
224+
setClickable(false);
225+
} else {
226+
// Restore normal interaction
227+
setFocusable(true);
228+
setClickable(true);
229+
}
230+
}
231+
232+
@Override
233+
public boolean isReadOnly() {
234+
return mReadOnly;
235+
}
236+
211237
@Override
212238
public boolean performClick() {
239+
// Block clicks when readonly
240+
if (mReadOnly) {
241+
return false;
242+
}
213243
super.performClick();
214244
new PopupDialog().show();
215245
return true;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.bspb.smartbirds.pro.ui.views;
2+
3+
/**
4+
* Interface for views that support read-only mode.
5+
*/
6+
public interface SupportReadOnly {
7+
/**
8+
* Set whether this view is in read-only mode.
9+
* When read-only, the view should:
10+
* - Display its current value
11+
* - Prevent user editing/interaction
12+
*
13+
* @param readOnly true to make the view read-only, false to allow editing
14+
*/
15+
void setReadOnly(boolean readOnly);
16+
17+
/**
18+
* Check if this view is currently in read-only mode.
19+
*
20+
* @return true if read-only, false otherwise
21+
*/
22+
boolean isReadOnly();
23+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.bspb.smartbirds.pro.forms.convert
2+
3+
import android.content.Context
4+
import org.bspb.smartbirds.pro.R
5+
6+
class BearsConverter(context: Context?) : Converter(context) {
7+
init {
8+
// Bats main form
9+
addBool(R.string.tag_confidential, "confidential")
10+
addBool(R.string.tag_moderator_review, "moderatorReview")
11+
add(R.string.tag_remarks_type, "speciesNotes")
12+
addMulti(R.string.tag_threats, "threats")
13+
14+
addSpecies(R.string.tag_species_scientific_name, "species")
15+
add(R.string.tag_count, "count", "0")
16+
addSingle(R.string.tag_sex, "sex")
17+
addSingle(R.string.tag_age, "age")
18+
addMulti(R.string.tag_excrement_content, "excrementContent")
19+
addSingle(R.string.tag_excrement_consistence, "excrementConsistence")
20+
add(R.string.tag_marking_height, "markingHeight")
21+
addSingle(R.string.tag_den, "den")
22+
addMulti(R.string.tag_habitat, "habitat")
23+
addMulti(R.string.tag_threats_other, "threatsBears")
24+
addMulti(R.string.tag_findings, "findings")
25+
26+
// Additional fields
27+
add(R.string.tag_footprint_front_paw_width, "footprintFrontPawWidth")
28+
add(R.string.tag_footprint_front_paw_length, "footprintFrontPawLength")
29+
add(R.string.tag_footprint_hind_paw_width, "footprintHindPawWidth")
30+
add(R.string.tag_footprint_hind_paw_length, "footprintHindPawLength")
31+
}
32+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.bspb.smartbirds.pro.forms.upload
2+
3+
import com.google.gson.JsonObject
4+
import org.bspb.smartbirds.pro.backend.SmartBirdsApi
5+
import org.bspb.smartbirds.pro.backend.dto.UploadFormResponse
6+
import retrofit2.Call
7+
8+
class BearsUploader : Uploader {
9+
override fun upload(api: SmartBirdsApi, data: JsonObject): Call<UploadFormResponse> {
10+
return api.createBear(data)
11+
}
12+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.bspb.smartbirds.pro.ui.fragment
2+
3+
import android.os.Bundle
4+
import androidx.fragment.app.Fragment
5+
import androidx.fragment.app.FragmentStatePagerAdapter
6+
import org.bspb.smartbirds.pro.R
7+
import org.bspb.smartbirds.pro.enums.EntryType
8+
9+
class NewBearsEntryFormFragment : BaseTabEntryFragment() {
10+
11+
override fun setupTabs() {
12+
setAdapter(object : FragmentStatePagerAdapter(parentFragmentManager) {
13+
override fun getItem(position: Int): Fragment {
14+
return when (position) {
15+
0 -> NewBearsEntryMainFormFragment.newInstance(isNewEntry, readOnly)
16+
1 -> NewBearsEntryOptionalFormFragment.newInstance(isNewEntry, readOnly)
17+
else -> throw IllegalArgumentException("Unhandled position$position")
18+
}
19+
}
20+
21+
override fun getPageTitle(position: Int): CharSequence {
22+
return activity!!.getString(if (position == 0) R.string.tab_required else R.string.tab_optional)
23+
}
24+
25+
override fun getCount(): Int {
26+
return 2
27+
}
28+
})
29+
}
30+
31+
override fun getEntryType(): EntryType? {
32+
return EntryType.BEARS
33+
}
34+
35+
class Builder : BaseEntryFragment.Builder {
36+
override fun build(lat: Double, lon: Double, geolocationAccuracy: Double): Fragment? {
37+
return NewBearsEntryFormFragment().apply {
38+
arguments = Bundle().apply {
39+
putDouble(ARG_LAT, lat)
40+
putDouble(ARG_LON, lon)
41+
putDouble(ARG_GEOLOCATION_ACCURACY, geolocationAccuracy)
42+
}
43+
}
44+
}
45+
46+
override fun load(id: Long, readOnly: Boolean): Fragment? {
47+
return NewBearsEntryFormFragment().apply {
48+
arguments = Bundle().apply {
49+
putLong(ARG_ENTRY_ID, id)
50+
putBoolean(ARG_READ_ONLY, readOnly)
51+
}
52+
}
53+
}
54+
}
55+
56+
}

0 commit comments

Comments
 (0)