Commit f02b9842 authored by Roger Barton's avatar Roger Barton
Browse files

Moved Events/Jobs to generic base class (Items in issue #7)

Combined Events and Jobs into the ApiListBase file, all functionality is now shared for managing the lists of events and jobs.
Events, Jobs inherit from ApiListBase
EventInfo, JobInfo inherti from ApiItemBase, for easy use within the ApiListBase
individual events/jobs can now be easily accessed by indexes, ids, or intent using the LauncherExtras in ApiListBase
JobDetailActivity can now be launched with such an intent as well.
parent 8e038daf
Pipeline #8800 passed with stages
in 3 minutes and 57 seconds
......@@ -31,6 +31,7 @@ import ch.amiv.android_app.R;
import ch.amiv.android_app.events.EventDetailActivity;
import ch.amiv.android_app.events.Events;
import ch.amiv.android_app.jobs.JobDetailActivity;
import ch.amiv.android_app.util.ApiListBase.LauncherExtras;
import ch.amiv.android_app.util.Util;
......@@ -246,16 +247,16 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
public void StartEventDetailActivity(int eventGroup, int eventIndex)
{
Intent intent = new Intent(this, EventDetailActivity.class);
intent.putExtra(EventDetailActivity.LauncherExtras.EVENT_GROUP, eventGroup);
intent.putExtra(EventDetailActivity.LauncherExtras.EVENT_INDEX, eventIndex);
intent.putExtra(LauncherExtras.ITEM_GROUP, eventGroup);
intent.putExtra(LauncherExtras.ITEM_INDEX, eventIndex);
startActivityForResult(intent, 0);
}
public void StartJobDetailActivity(int jobGroup, int jobIndex)
{
Intent intent = new Intent(this, JobDetailActivity.class);
intent.putExtra(JobDetailActivity.LauncherExtras.JOB_GROUP, jobGroup);
intent.putExtra(JobDetailActivity.LauncherExtras.JOB_INDEX, jobIndex);
intent.putExtra(LauncherExtras.ITEM_GROUP, jobGroup);
intent.putExtra(LauncherExtras.ITEM_INDEX, jobIndex);
startActivityForResult(intent, 0);
}
......@@ -275,7 +276,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
public void OnDataReceived() {
SetLoginUIDirty();
//Update events and signups with the new userinfo
if(Events.eventInfos.size() > 0)
if(Events.get.data.size() > 0)
Request.FetchEventSignups(getApplicationContext(), pages.get(ListFragment.PageType.EVENTS).onEventsListUpdatedCallback, null, "");
else
Request.FetchEventList(getApplicationContext(), pages.get(ListFragment.PageType.EVENTS).onEventsListUpdatedCallback, null, "");
......
......@@ -16,6 +16,7 @@ import java.util.Calendar;
import ch.amiv.android_app.R;
import ch.amiv.android_app.events.EventDetailActivity;
import ch.amiv.android_app.events.Events;
import ch.amiv.android_app.util.ApiListBase;
public final class Notifications {
public static AlarmManager alarm;
......@@ -109,92 +110,81 @@ public final class Notifications {
*/
public static void event_notifier (Context context, JSONObject json){
// TODO catch when projections are used
try{
try{
JSONArray items = json.getJSONArray("_items");
JSONArray items = json.getJSONArray("_items");
if(items.length()!=0) {
if(items.length()!=0) {
// for one new event -> notify and onClick show details
if(items.length()==1) {
// for one new event -> notify and onClick show details
if(items.length()==1) {
// get event from JSONObject and add it to events list
JSONObject event = items.getJSONObject(0);
Events.AddEvent(event, context);
// get event from JSONObject and add it to events list
JSONObject event = items.getJSONObject(0);
Events.get.AddItem(event, context);
// refetch event list to add new event
String event_id = (String) event.get("_id");
Request.FetchEventList(context, null, null, event_id);
// refetch event list to add new event
String event_id = (String) event.get("_id");
Request.FetchEventList(context, null, null, event_id);
// generate pending intent to get EventDetails onClick
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
// generate pending intent to get EventDetails onClick
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, EventDetailActivity.class);
notificationIntent.putExtra(EventDetailActivity.LauncherExtras.EVENT_ID, event_id);
notificationIntent.putExtra(EventDetailActivity.LauncherExtras.LOAD_EVENTS, true);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent notificationIntent = new Intent(context, EventDetailActivity.class);
notificationIntent.putExtra(ApiListBase.LauncherExtras.ITEM_ID, event_id);
notificationIntent.putExtra(ApiListBase.LauncherExtras.RELOAD_FIRST, true);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// generate notification
String title = (String) event.get("title_de");
Notifications.notify_pending(context, "New Event added", title, R.drawable.ic_amiv_logo_icon, pendingIntent);
}
// multiple new events -> show all titles and onClick show events main page
else{
// get event id's from new events
String [] event_id = new String[items.length()];
for(int i = 0; i<items.length();i++){
JSONObject event = items.getJSONObject(i);
Events.AddEvent(event, context); // TODO efficiency !
event_id[i]= (String) event.get("_id");
}
// add new events to list
// TODO how -> new function?
Request.FetchEventList(context, null, null,event_id[0]); // TODO not null !
// onClick start main activity
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// build string to display all event titles
StringBuilder titles_list = new StringBuilder();
titles_list.append ((String)items.getJSONObject(0).get("title_de"));
for(int j = 1; j<items.length();j++){
titles_list.append(", ");
titles_list.append((String)items.getJSONObject(j).get("title_de"));
}
Notifications.notify_pending(context, "Many new Events added", titles_list.toString(), R.drawable.ic_amiv_logo_icon, pendingIntent);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// generate notification
String title = (String) event.get("title_de");
Notifications.notify_pending(context, "New Event added", title, R.drawable.ic_amiv_logo_icon, pendingIntent);
}
// multiple new events -> show all titles and onClick show events main page
else{
// get event id's from new events
String [] event_id = new String[items.length()];
for(int i = 0; i<items.length();i++){
JSONObject event = items.getJSONObject(i);
Events.get.AddItem(event, context); // TODO efficiency !
event_id[i]= (String) event.get("_id");
}
// add new events to list
// TODO how -> new function?
Request.FetchEventList(context, null, null,event_id[0]); // TODO not null !
// onClick start main activity
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// build string to display all event titles
StringBuilder titles_list = new StringBuilder();
titles_list.append ((String)items.getJSONObject(0).get("title_de"));
for(int j = 1; j<items.length();j++){
titles_list.append(", ");
titles_list.append((String)items.getJSONObject(j).get("title_de"));
}
Notifications.notify_pending(context, "Many new Events added", titles_list.toString(), R.drawable.ic_amiv_logo_icon, pendingIntent);
}
}
// sets last change check to current time
String dat = Request.dateFormat.format(Calendar.getInstance().getTime());
Settings.SetPref(Settings.last_change_check_dateKey,dat,context);
}catch(JSONException ex){
// TODO
}
// sets last change check to current time
String dat = Request.dateFormat.format(Calendar.getInstance().getTime());
Settings.SetPref(Settings.last_change_check_dateKey,dat,context);
}catch(JSONException ex){
// TODO
}
}
}
......@@ -201,9 +201,9 @@ public final class Request {
public void run() {
try {
if(eventId.isEmpty())
Events.UpdateEventInfos(context, json.getJSONArray("_items"));
Events.get.UpdateAll(context, json.getJSONArray("_items"));
else
Events.UpdateSingleEvent(json, eventId);
Events.get.UpdateItem(json, eventId, context);
if(callback != null)
callback.OnDataReceived();
} catch (JSONException e) {
......@@ -260,7 +260,7 @@ public final class Request {
}
/**
* Will fetch the event signups for the current user and save them in the eventInfos list
* Will fetch the event signups for the current user and save them in the data list
* @param eventId to only fetch for a specific event id add this, else set as empty
*/
public static void FetchEventSignups(final Context context, final OnDataReceivedCallback callback, final OnDataReceivedCallback errorCallback, @NonNull String eventId)
......@@ -289,7 +289,7 @@ public final class Request {
Runnable runnable = new Runnable() {
@Override
public void run() {
Events.AddSignupArray(signupsJson);
Events.get.AddSignupArray(signupsJson);
if(callback != null)
callback.OnDataReceived();
}
......@@ -366,9 +366,9 @@ public final class Request {
public void run() {
try {
if(jobId.isEmpty())
Jobs.UpdateJobInfos(context, json.getJSONArray("_items"));
Jobs.get.UpdateAll(context, json.getJSONArray("_items"));
else
Jobs.UpdateSingleJob(json, jobId);
Jobs.get.UpdateItem(json, jobId, context);
if(callback != null)
callback.OnDataReceived();
} catch (JSONException e) {
......
......@@ -269,7 +269,7 @@ public class Settings {
public static void SaveEvents(Context context)
{
Gson gson = new Gson();
String json = gson.toJson(Events.eventInfos, eventListType);
String json = gson.toJson(Events.get.data, eventListType);
SetPref(eventInfoKey, json, context);
}
......@@ -283,8 +283,8 @@ public class Settings {
try {
Gson gson = new Gson();
Events.eventInfos = gson.fromJson(json, eventListType);
Events.GenerateSortedLists(true);
Events.get.data = gson.fromJson(json, eventListType);
Events.get.GenerateSortedLists(true);
}
catch (Exception e){ //This may happen if the userinfo class changes
e.printStackTrace();
......@@ -304,7 +304,7 @@ public class Settings {
public static void SaveJobs(Context context)
{
Gson gson = new Gson();
String json = gson.toJson(Jobs.jobInfos, jobListType);
String json = gson.toJson(Jobs.get.data, jobListType);
SetPref(jobInfoKey, json, context);
}
......@@ -318,8 +318,8 @@ public class Settings {
try {
Gson gson = new Gson();
Jobs.jobInfos = gson.fromJson(json, jobListType);
Jobs.GenerateSortedLists(true);
Jobs.get.data = gson.fromJson(json, jobListType);
Jobs.get.GenerateSortedLists(true);
}
catch (Exception e){ //This may happen if the userinfo class changes
e.printStackTrace();
......
......@@ -142,7 +142,7 @@ public class UserInfo implements Serializable{
else {
//delete session at the server and then clear the token
Request.DeleteCurrentSession(context);
Events.ClearSignups();
Events.get.ClearSignups();
}
Settings.ClearUser(context);
......
......@@ -22,8 +22,8 @@ public class MainActivity extends AppCompatActivity {
String firstname = UserInfo.current.firstname;
//To access events use
EventInfo eventInfo = Events.sortedEventInfos.get(0).get(1);//sorted into groups by date
eventInfo = Events.eventInfos.get(0);//unsorted list
EventInfo eventInfo = Events.sorted.get(0).get(1);//sorted into groups by date
eventInfo = Events.data.get(0);//unsorted list
//To Send a request to the api or elsewhere see core.Request class for examples. Basic structure is as below
//START of request
......
......@@ -54,23 +54,14 @@ import ch.amiv.android_app.util.Util;
* This mainly displays stored info about the event, eg description and also fetches more such as images. Also handles registering for and event and the possible outcomes
*
* To launch this activity, you need to provide an event to view. You need to provide this as an intent extra (use intent.putExtra()):
* - Provide eventGroup == -1, eventGroup == index in Events.eventInfos (unsorted list)
* - Provide eventGroup == group in Events.sortedEventInfos, eventGroup == index in Events.sortedEventInfos (sorted list)
* - Provide eventGroup == -1, eventGroup == index in Events.data (unsorted list)
* - Provide eventGroup == group in Events.sorted, eventGroup == index in Events.sorted (sorted list)
* - Provide eventId == any valid event id
*
* If the event is not found, the activity finishes and returns to the calling activity.
*/
public class EventDetailActivity extends AppCompatActivity {
/**
* A constant class to easily set extras for launching the EventDetailActivity
*/
public static final class LauncherExtras {
public static final String EVENT_GROUP = "eventGroup";
public static final String EVENT_INDEX = "eventIndex";
public static final String EVENT_ID = "eventId";
public static final String LOAD_EVENTS = "loadEvents";
}
//region - Variables
private EventInfo event;
private ImageView posterImage;
......@@ -107,6 +98,19 @@ public class EventDetailActivity extends AppCompatActivity {
swipeRefreshLayout.setRefreshing(false);
}
};
//endregion
/**
* This will retrieve the eventIndexes to display, is only set when we originate from the MainActivity, where the int is added to the intent.
*/
private void GetIntentData (){
Intent intent = getIntent();
event = Events.get.GetItem(intent, getApplicationContext());
if(event == null)
ReturnToCallingActivity(false);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -159,39 +163,6 @@ public class EventDetailActivity extends AppCompatActivity {
finish();
}
/**
* This will retrieve the eventIndexes to display, is only set when we originate from the MainActivity, where the int is added to the intent.
*/
private void GetIntentData (){
Intent intent = getIntent();
if(intent.getBooleanExtra(LauncherExtras.LOAD_EVENTS, false))
Settings.LoadEvents(getApplicationContext());
if(intent.hasExtra(LauncherExtras.EVENT_GROUP) && intent.hasExtra(LauncherExtras.EVENT_INDEX))
{
int eventGroup = intent.getIntExtra(LauncherExtras.EVENT_GROUP, 0);
int eventIndex = intent.getIntExtra(LauncherExtras.EVENT_INDEX, 0);
if(eventGroup == -1)
event = Events.eventInfos.get(eventIndex);
else
event = Events.sortedEventInfos.get(eventGroup).get(eventIndex);
if (event == null)
Log.e("events", "invalid event index selected during InitUI(), (groupIndex, eventIndex): (" + eventGroup + "," + eventIndex + "), total event size" + Events.eventInfos.size() + ". Ensure that you are not clearing/overwriting the events list while viewing an event. Returning to calling activity...");
}
else if(intent.hasExtra(LauncherExtras.EVENT_ID))
{
event = Events.GetEventById(intent.getStringExtra(LauncherExtras.EVENT_ID));
if(event == null)
Log.e("events", "No event found from eventId=" + intent.getStringExtra(LauncherExtras.EVENT_ID) + " in intent, have you used intent.putStringExtra. Returning to calling activity...");
}
if(event == null)
ReturnToCallingActivity(false);
}
/**
* This initialises UI variables and sets up various UI elements
*/
......
......@@ -15,6 +15,7 @@ import java.util.Locale;
import ch.amiv.android_app.R;
import ch.amiv.android_app.core.Request;
import ch.amiv.android_app.util.ApiItemBase;
import ch.amiv.android_app.util.Util;
import static ch.amiv.android_app.util.Util.BuildFileUrl;
......@@ -22,9 +23,9 @@ import static ch.amiv.android_app.util.Util.BuildFileUrl;
/**
* This is all the data about one event AND the current users signup data about that event
*/
public class EventInfo implements Serializable{
public class EventInfo extends ApiItemBase implements Serializable{
//region - ====Variables====
public String _id;
//public String _id; //inherited from ApiItemBase
public String _etag;
private String title_de;
private String title_en;
......@@ -74,13 +75,13 @@ public class EventInfo implements Serializable{
//endregion
public EventInfo(JSONObject json) {
UpdateEvent(json);
Update(json);
}
/**
* Overwrite the current data
*/
public void UpdateEvent(JSONObject json)
public void Update(JSONObject json)
{
_id = json.optString("_id");
_etag = json.optString("_etag");
......
package ch.amiv.android_app.events;
import android.content.Context;
import android.support.annotation.NonNull;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import ch.amiv.android_app.core.Settings;
import ch.amiv.android_app.util.ApiListBase;
/**
* This is the central place for storing information about the events, events + signups.
* Attention! eventInfo and sortedEventInfos indexes may change, the events will allways be sorted according to the adDateComparator.
* Attention! eventInfo and sorted indexes may change, the events will allways be sorted according to the adDateComparator.
*/
public final class Events {
public static List<EventInfo> eventInfos = new ArrayList<EventInfo>(); //This is a list of ALL events as received from the api, we will not use this directly
public static List<List<EventInfo>> sortedEventInfos = new ArrayList<>(EventGroup.SIZE); //A list of lists which has been sorted according to the EventGroup configuration
public class Events extends ApiListBase<EventInfo> {
//region - Variables
public static Events get = new Events();
public static boolean[] invertEventGroupSorting = new boolean[] {false, false, false, true}; //used to invert date sorting for the event groups
public static final int DAYS_NEW_TAG_ACTIVE = 3; //Defines for how many days after the ad start date the new tag is visible for
/**
* Use this class to use the correct indexes for the event group for the sorted list.
* Sidenote: we use the term 'group' and 'category' interchangeably
*/
//Use this class to use the correct indexes for the event group for the sortedEventInfos list
public static final class EventGroup {
public static final int SIZE = 4;
public static final int HIDDEN_EVENTS = 0;
public static final int CURRENT_EVENTS = 1;
public static final int CLOSED_EVENTS = 2;
public static final int PAST_EVENTS = 3;
}
//Defines for how many days after the ad start date the new tag is visible for
public static final int DAYS_NEW_TAG_ACTIVE = 3;
private static final int HIDDEN_EVENTS_EXP_SIZE = 2;
private static final int CURRENT_EVENTS_EXP_SIZE = 10;
private static final int CLOSED_EVENTS_EXP_SIZE = 5;
private static final int PAST_EVENTS_EXP_SIZE = 20;
}
private static Comparator<EventInfo> adDateComparator = new Comparator<EventInfo>() {
@Override
......@@ -45,159 +51,82 @@ public final class Events {
}
};
/**
* This is the key function of this class. It converts a json for several events to java EventInfos
* Update the event infos with the data received from the api. This is just for updating information about the event NOT the signup
* @param json json array of the events.
*/
public static void UpdateEventInfos(Context context, JSONArray json)
{
boolean isInitialising = eventInfos.size() == 0;
for (int i = 0; i < json.length(); i++)
{
try {
//if we are not initialising, search for the event id and then update it, else add a new one to the list. This ensures we do not lose the signup data
JSONObject jsonEvent = json.getJSONObject(i);
EventInfo e = new EventInfo(jsonEvent);
if(e._id.isEmpty())
continue;
if(isInitialising || !UpdateSingleEvent(jsonEvent, e._id))
eventInfos.add(e);
} catch (JSONException e) {
e.printStackTrace();
}
}
GenerateSortedLists(isInitialising);
Settings.SaveEvents(context);
}
public static void GenerateSortedLists(boolean isInitialising)
{
if(isInitialising){
sortedEventInfos = new ArrayList<>(EventGroup.SIZE);
for (int k = 0; k < EventGroup.SIZE; k++)
sortedEventInfos.add(new ArrayList<EventInfo>());
}
else {
for (int k = 0; k < sortedEventInfos.size(); k++)
sortedEventInfos.get(k).clear();
}
//Sort list and update sorted list
if(!eventInfos.isEmpty()){
//sort so first elem has an advertising start date furthest in the future
Collections.sort(eventInfos, adDateComparator);
//fill in the sorted list according to the dates of the events
for (int i = 0; i < eventInfos.size(); i++){
AddEventToSorted(eventInfos.get(i), false);
}
}
@Override
public Comparator<EventInfo> GetItemComparator() {
return adDateComparator;
}
//endregion
//region - Override functions from ApiListBase
/**
* Will add the event to the sorted array. Use AddEvent to add an event, this is just used to update the sortedEventInfos list accordingly
* @param sortAfterInsert Will resort the group after insertion, by date
* @return An instance of EventInfo parsed from the json
*/
private static void AddEventToSorted(EventInfo eventInfo, boolean sortAfterInsert){
Date today = Calendar.getInstance().getTime();
int group;
if(eventInfo.time_advertising_start.after(today)) //Determine which group the event is in, by date
group = EventGroup.HIDDEN_EVENTS;
else if(eventInfo.time_register_end.after(today))
group = EventGroup.CURRENT_EVENTS;
else if(eventInfo.time_end.after(today))
group = EventGroup.CLOSED_EVENTS;
else
group = EventGroup.PAST_EVENTS;
if(sortedEventInfos == null || sortedEventInfos.size() == 0)
GenerateSortedLists(true);
else
sortedEventInfos.get(group).add(eventInfo);
if(sortAfterInsert) {
Collections.sort(eventInfos, adDateComparator);
Collections.sort(sortedEventInfos.get(group), adDateComparator);
}