Added new coursework, cleaned up structure

This commit is contained in:
2017-11-29 10:11:54 -08:00
parent b300c76103
commit 808a0f1724
345 changed files with 126653 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.corwinperren.cs496finalandroid">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".NewProjectActivity" android:windowSoftInputMode="stateHidden"></activity>
<activity android:name=".EditProjectActivity" android:windowSoftInputMode="stateHidden"></activity>
<activity android:name=".ReminderListingActivity" android:windowSoftInputMode="stateHidden"></activity>
<activity android:name=".ReminderViewActivity" android:windowSoftInputMode="stateHidden"></activity>
<activity android:name=".ReminderEditActivity" android:windowSoftInputMode="stateHidden"></activity>
<activity android:name=".NewReminderActivity" android:windowSoftInputMode="stateHidden"></activity>
</application>
</manifest>

View File

@@ -0,0 +1,11 @@
package com.example.corwinperren.cs496finalandroid;
public class APIUrls {
public static String scheme = "https://";
public static String host = "cs496-final-gae.appspot.com";
public static String base_url = scheme + host;
public static String get_projects_url = base_url + "/projects";
public static String post_projects_url = get_projects_url;
}

View File

@@ -0,0 +1,309 @@
package com.example.corwinperren.cs496finalandroid;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class EditProjectActivity extends AppCompatActivity {
EditText project_name_edit_text;
EditText project_language_edit_text;
EditText contributor_name_edit_text;
Button project_submit_update_button;
Button project_delete_button;
Button contributor_add_button;
Button contributor_remove_button;
ListView contributor_list_view;
List<String> contributor_string_list = new ArrayList<>();
ArrayAdapter<String> contributor_array_adapter;
int selected_contributor_position = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_or_edit_project);
get_view_resources();
setup_button_handlers();
setup_view_resources();
}
@Override
protected void onResume(){
super.onResume();
load_project();
}
private void load_project(){
contributor_array_adapter.clear();
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
HttpUrl reqUrl = HttpUrl.parse(APIUrls.get_projects_url + "/" + project_id);
Request request = new Request.Builder().url(reqUrl).get().build();
mOkHttpClient.newCall(request).enqueue(load_project_callback);
}
private void delete_project(){
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
HttpUrl reqUrl = HttpUrl.parse(APIUrls.get_projects_url + "/" + project_id);
Request request = new Request.Builder().url(reqUrl).delete().build();
mOkHttpClient.newCall(request).enqueue(delete_project_callback);
}
private void update_project(){
String name = project_name_edit_text.getText().toString();
String language = project_language_edit_text.getText().toString();
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
if(name.equals("")){
show_toast_text("Project Name Required...");
return;
}
OkHttpClient mOkHttpClient = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
JSONObject json_body = new JSONObject();
try {
json_body.put("name", name);
json_body.put("language", language);
json_body.put("contributors", new JSONArray(contributor_string_list));
} catch(Exception e1){
e1.printStackTrace();
}
RequestBody body = RequestBody.create(JSON, json_body.toString());
HttpUrl reqUrl = HttpUrl.parse(APIUrls.post_projects_url + "/" + project_id);
Request request = new Request.Builder()
.url(reqUrl)
.put(body)
.build();
mOkHttpClient.newCall(request).enqueue(update_project_callback);
}
public Callback load_project_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Load project failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
try {
JSONObject http_response = new JSONObject(callback_response);
String name = http_response.getString("name");
String language = http_response.getString("language");
JSONArray contributors = http_response.getJSONArray("contributors");
update_ui_with_project(name, language, contributors);
}catch (JSONException e1) {
e1.printStackTrace();
}
}
};
public Callback delete_project_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Delete project failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
show_toast_text("Deleted project successfully!");
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
Intent intent = new Intent(EditProjectActivity.this, MainActivity.class);
startActivity(intent);
}
};
public Callback update_project_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Update project failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
show_toast_text("Updated project successfully!");
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
Intent intent = new Intent(EditProjectActivity.this, MainActivity.class);
startActivity(intent);
}
};
private void update_ui_with_project(final String name, final String language, final JSONArray contributors){
runOnUiThread(new Runnable() {
@Override
public void run() {
project_name_edit_text.setText(name);
if(!language.equals("null")) {
project_language_edit_text.setText(language);
}
for(int i = 0 ; i < contributors.length() ; i++){
try {
contributor_string_list.add(contributors.getString(i));
}catch (JSONException e1) {
e1.printStackTrace();
}
}
contributor_array_adapter.notifyDataSetChanged();
}
});
}
AdapterView.OnItemClickListener contributor_click_listener = new AdapterView.OnItemClickListener (){
@Override
public void onItemClick(AdapterView<?> parent, View current_list_item, int position, long id){
clear_row_background_colors();
current_list_item.setBackgroundColor(getColor(android.R.color.holo_orange_light));
selected_contributor_position = position;
contributor_remove_button.setEnabled(true);
}
};
private void clear_row_background_colors(){
for(Integer i = 0 ; i < contributor_list_view.getChildCount() ; i++){
contributor_list_view.getChildAt(i).setBackground(null);
}
}
private void get_view_resources(){
project_name_edit_text = (EditText) findViewById(R.id.project_name_edit_text);
project_language_edit_text = (EditText) findViewById(R.id.project_language_edit_text);
contributor_name_edit_text = (EditText) findViewById(R.id.contributor_name_edit_text);
project_submit_update_button = (Button) findViewById(R.id.project_submit_update_button);
project_delete_button = (Button) findViewById(R.id.project_delete_button);
contributor_add_button = (Button) findViewById(R.id.contributor_add_button);
contributor_remove_button = (Button) findViewById(R.id.contributor_remove_button);
contributor_list_view = (ListView) findViewById(R.id.contributor_list_view);
}
private void setup_button_handlers(){
project_submit_update_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
update_project();
}
});
project_delete_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
delete_project();
}
});
contributor_add_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
contributor_string_list.add(contributor_name_edit_text.getText().toString());
contributor_array_adapter.notifyDataSetChanged();
contributor_name_edit_text.setText("");
}
});
contributor_remove_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Log.d(MainActivity.TAG, String.valueOf(selected_contributor_position));
contributor_string_list.remove(selected_contributor_position);
contributor_array_adapter.notifyDataSetChanged();
clear_row_background_colors();
contributor_remove_button.setEnabled(false);
}
});
}
private void setup_view_resources(){
project_submit_update_button.setText("Update");
contributor_array_adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contributor_string_list);
contributor_list_view.setAdapter(contributor_array_adapter);
contributor_list_view.setOnItemClickListener(contributor_click_listener);
}
private void show_toast_text(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
}
}

View File

@@ -0,0 +1,237 @@
package com.example.corwinperren.cs496finalandroid;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
TableLayout projects_table_layout;
Button new_project_button;
Button edit_project_button;
Button edit_reminders_button;
JSONArray http_response;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
get_view_resources();
setup_button_handlers();
}
@Override
protected void onResume(){
super.onResume();
load_projects();
}
private void get_view_resources(){
projects_table_layout = (TableLayout) findViewById(R.id.projects_table_layout);
new_project_button = (Button) findViewById(R.id.new_project_button);
edit_project_button = (Button) findViewById(R.id.edit_project_button);
edit_reminders_button = (Button) findViewById(R.id.edit_reminders_button);
}
private void load_projects(){
clear_projects();
OkHttpClient mOkHttpClient = new OkHttpClient();
HttpUrl reqUrl = HttpUrl.parse(APIUrls.get_projects_url);
Request request = new Request.Builder().url(reqUrl).get().build();
mOkHttpClient.newCall(request).enqueue(load_projects_callback);
}
public Callback load_projects_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(TAG, callback_response);
try {
http_response = new JSONArray(callback_response);
Integer num_projects = http_response.length();
if(num_projects == 0){
edit_project_button.setEnabled(false);
edit_reminders_button.setEnabled(false);
return;
}
for (Integer index = 0 ; index < num_projects ; index++){
JSONObject current_project = http_response.getJSONObject(index);
String name = current_project.getString("name");
String language = current_project.getString("language");
JSONArray contributors = current_project.getJSONArray("contributors");
String project_id = current_project.getString("id");
add_row_to_table(name, language, contributors, project_id);
}
}catch (JSONException e1) {
e1.printStackTrace();
}
select_first_project();
}
private void add_row_to_table(final String name, final String language, final JSONArray contributors, final String project_id){
runOnUiThread(new Runnable() {
@Override
public void run() {
TableRow newRow = new TableRow(MainActivity.this);
TextView nameTextView = new TextView(MainActivity.this);
TextView languageTextView = new TextView(MainActivity.this);
TextView contributorsTextView = new TextView(MainActivity.this);
nameTextView.setText(name);
if(!language.equals("null")) {
languageTextView.setText(language);
}
String contributors_string = "";
for(Integer i = 0 ; i < contributors.length() ; i++){
if(i != 0 ){ contributors_string += "\n"; }
try {
contributors_string += contributors.getString(i);
}catch (JSONException e1) {
e1.printStackTrace();
}
}
contributorsTextView.setText(contributors_string);
newRow.addView(nameTextView);
newRow.addView(languageTextView);
newRow.addView(contributorsTextView);
newRow.setTag(project_id);
newRow.setClickable(true);
newRow.setOnClickListener(row_click_listener);
projects_table_layout.addView(newRow, new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT));
}
});
}
};
View.OnClickListener row_click_listener = new View.OnClickListener(){
@Override
public void onClick(View current_row){
clear_row_background_colors();
current_row.setBackgroundColor(getColor(android.R.color.holo_orange_light));
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
app_preferences.edit().putString("selected_project", current_row.getTag().toString()).apply();
edit_project_button.setEnabled(true);
edit_reminders_button.setEnabled(true);
}
};
private void clear_projects(){
int numTableRows = projects_table_layout.getChildCount();
if (numTableRows > 1){
projects_table_layout.removeViews(1, numTableRows - 1);
}
}
private void select_first_project(){
runOnUiThread(new Runnable() {
@Override
public void run() {
if(projects_table_layout.getChildCount() > 1){
TableRow row = (TableRow) projects_table_layout.getChildAt(1);
row.performClick();
}
}
});
}
private void clear_row_background_colors(){
for(Integer i = 0 ; i < projects_table_layout.getChildCount() ; i++){
TableRow row = (TableRow) projects_table_layout.getChildAt(i);
row.setBackground(null);
}
}
private void show_toast_text(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
}
private void setup_button_handlers(){
new_project_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, NewProjectActivity.class);
startActivity(intent);
}
});
edit_project_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, EditProjectActivity.class);
startActivity(intent);
}
});
edit_reminders_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, ReminderListingActivity.class);
startActivity(intent);
}
});
}
}

View File

@@ -0,0 +1,199 @@
package com.example.corwinperren.cs496finalandroid;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import com.example.corwinperren.cs496finalandroid.APIUrls;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class NewProjectActivity extends AppCompatActivity {
EditText project_name_edit_text;
EditText project_language_edit_text;
EditText contributor_name_edit_text;
Button project_submit_update_button;
Button project_delete_button;
Button contributor_add_button;
Button contributor_remove_button;
ListView contributor_list_view;
List<String> contributor_string_list = new ArrayList<>();
ArrayAdapter<String> contributor_array_adapter;
int selected_contributor_position = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_or_edit_project);
get_view_resources();
setup_button_handlers();
setup_view_resources();
}
private void submit_new_project(){
String name = project_name_edit_text.getText().toString();
String language = project_language_edit_text.getText().toString();
if(name.equals("")){
show_toast_text("Project Name Required...");
return;
}
OkHttpClient mOkHttpClient = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
JSONObject json_body = new JSONObject();
try {
json_body.put("name", name);
json_body.put("language", language);
json_body.put("contributors", new JSONArray(contributor_string_list));
} catch(Exception e1){
e1.printStackTrace();
}
RequestBody body = RequestBody.create(JSON, json_body.toString());
HttpUrl reqUrl = HttpUrl.parse(APIUrls.post_projects_url);
Request request = new Request.Builder()
.url(reqUrl)
.post(body)
.build();
mOkHttpClient.newCall(request).enqueue(post_project_callback);
}
public Callback post_project_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Adding project failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
show_toast_text("Project added successfully!");
Intent intent = new Intent(NewProjectActivity.this, MainActivity.class);
startActivity(intent);
}
};
AdapterView.OnItemClickListener contributor_click_listener = new AdapterView.OnItemClickListener (){
@Override
public void onItemClick(AdapterView<?> parent, View current_list_item, int position, long id){
clear_row_background_colors();
current_list_item.setBackgroundColor(getColor(android.R.color.holo_orange_light));
selected_contributor_position = position;
contributor_remove_button.setEnabled(true);
}
};
private void clear_row_background_colors(){
for(Integer i = 0 ; i < contributor_list_view.getChildCount() ; i++){
contributor_list_view.getChildAt(i).setBackground(null);
}
}
private void get_view_resources(){
project_name_edit_text = (EditText) findViewById(R.id.project_name_edit_text);
project_language_edit_text = (EditText) findViewById(R.id.project_language_edit_text);
contributor_name_edit_text = (EditText) findViewById(R.id.contributor_name_edit_text);
project_submit_update_button = (Button) findViewById(R.id.project_submit_update_button);
project_delete_button = (Button) findViewById(R.id.project_delete_button);
contributor_add_button = (Button) findViewById(R.id.contributor_add_button);
contributor_remove_button = (Button) findViewById(R.id.contributor_remove_button);
contributor_list_view = (ListView) findViewById(R.id.contributor_list_view);
}
private void setup_button_handlers(){
project_submit_update_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
submit_new_project();
}
});
contributor_add_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
contributor_string_list.add(contributor_name_edit_text.getText().toString());
contributor_array_adapter.notifyDataSetChanged();
contributor_name_edit_text.setText("");
}
});
contributor_remove_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Log.d(MainActivity.TAG, String.valueOf(selected_contributor_position));
contributor_string_list.remove(selected_contributor_position);
contributor_array_adapter.notifyDataSetChanged();
clear_row_background_colors();
contributor_remove_button.setEnabled(false);
}
});
}
private void setup_view_resources(){
project_submit_update_button.setText("Submit");
project_delete_button.setVisibility(View.INVISIBLE);
contributor_array_adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contributor_string_list);
contributor_list_view.setAdapter(contributor_array_adapter);
contributor_list_view.setOnItemClickListener(contributor_click_listener);
}
private void show_toast_text(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
}
}

View File

@@ -0,0 +1,203 @@
package com.example.corwinperren.cs496finalandroid;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class NewReminderActivity extends AppCompatActivity {
EditText new_edit_reminder_title_edit_text;
EditText new_edit_reminder_date_edit_text;
EditText new_edit_reminder_text_content_edit_text;
EditText new_edit_reminder_users_add_edit_text;
Button new_edit_reminder_add_edit_button;
Button new_edit_reminder_delete_button;
Button new_edit_reminder_user_add_button;
Button new_edit_reminder_user_remove_button;
ListView new_edit_reminder_user_list_view;
List<String> user_string_list = new ArrayList<>();
ArrayAdapter<String> user_array_adapter;
int selected_user_position = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_or_edit_reminder);
get_view_resources();
setup_button_handlers();
setup_view_resources();
}
private void submit_new_reminder(){
String title = new_edit_reminder_title_edit_text.getText().toString();
String reminder_date = new_edit_reminder_date_edit_text.getText().toString();
String text_content = new_edit_reminder_text_content_edit_text.getText().toString();
if(title.equals("")){
show_toast_text("Reminder Name Required...");
return;
}
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
JSONObject json_body = new JSONObject();
try {
json_body.put("title", title);
json_body.put("reminder_date", reminder_date);
json_body.put("users_to_notify", new JSONArray(user_string_list));
json_body.put("text_content", text_content);
} catch(Exception e1){
e1.printStackTrace();
}
RequestBody body = RequestBody.create(JSON, json_body.toString());
HttpUrl reqUrl = HttpUrl.parse(APIUrls.post_projects_url + "/" + project_id + "/reminders");
Request request = new Request.Builder()
.url(reqUrl)
.post(body)
.build();
mOkHttpClient.newCall(request).enqueue(post_reminder_callback);
}
public Callback post_reminder_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Adding reminder failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
show_toast_text("Reminder added successfully!");
Intent intent = new Intent(NewReminderActivity.this, ReminderListingActivity.class);
startActivity(intent);
}
};
AdapterView.OnItemClickListener user_list_click_listener = new AdapterView.OnItemClickListener (){
@Override
public void onItemClick(AdapterView<?> parent, View current_list_item, int position, long id){
clear_row_background_colors();
current_list_item.setBackgroundColor(getColor(android.R.color.holo_orange_light));
selected_user_position = position;
new_edit_reminder_user_remove_button.setEnabled(true);
}
};
private void clear_row_background_colors(){
for(Integer i = 0 ; i < new_edit_reminder_user_list_view.getChildCount() ; i++){
new_edit_reminder_user_list_view.getChildAt(i).setBackground(null);
}
}
private void show_toast_text(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
}
private void get_view_resources(){
new_edit_reminder_title_edit_text = (EditText) findViewById(R.id.new_edit_reminder_title_edit_text);
new_edit_reminder_date_edit_text = (EditText) findViewById(R.id.new_edit_reminder_date_edit_text);
new_edit_reminder_text_content_edit_text = (EditText) findViewById(R.id.new_edit_reminder_text_content_edit_text);
new_edit_reminder_users_add_edit_text = (EditText) findViewById(R.id.new_edit_reminder_users_add_edit_text);
new_edit_reminder_add_edit_button = (Button) findViewById(R.id.new_edit_reminder_add_edit_button);
new_edit_reminder_delete_button = (Button) findViewById(R.id.new_edit_reminder_delete_button);
new_edit_reminder_user_add_button = (Button) findViewById(R.id.new_edit_reminder_user_add_button);
new_edit_reminder_user_remove_button = (Button) findViewById(R.id.new_edit_reminder_user_remove_button);
new_edit_reminder_user_list_view = (ListView) findViewById(R.id.new_edit_reminder_user_list_view);
}
private void setup_button_handlers(){
new_edit_reminder_add_edit_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
submit_new_reminder();
}
});
new_edit_reminder_user_add_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
user_string_list.add(new_edit_reminder_users_add_edit_text.getText().toString());
user_array_adapter.notifyDataSetChanged();
new_edit_reminder_users_add_edit_text.setText("");
}
});
new_edit_reminder_user_remove_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
user_string_list.remove(selected_user_position);
user_array_adapter.notifyDataSetChanged();
clear_row_background_colors();
new_edit_reminder_user_remove_button.setEnabled(false);
}
});
}
private void setup_view_resources(){
new_edit_reminder_add_edit_button.setText("Submit");
new_edit_reminder_delete_button.setVisibility(View.INVISIBLE);
user_array_adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, user_string_list);
new_edit_reminder_user_list_view.setAdapter(user_array_adapter);
new_edit_reminder_user_list_view.setOnItemClickListener(user_list_click_listener);
}
}

View File

@@ -0,0 +1,313 @@
package com.example.corwinperren.cs496finalandroid;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class ReminderEditActivity extends AppCompatActivity {
EditText new_edit_reminder_title_edit_text;
EditText new_edit_reminder_date_edit_text;
EditText new_edit_reminder_text_content_edit_text;
EditText new_edit_reminder_users_add_edit_text;
Button new_edit_reminder_add_edit_button;
Button new_edit_reminder_delete_button;
Button new_edit_reminder_user_add_button;
Button new_edit_reminder_user_remove_button;
ListView new_edit_reminder_user_list_view;
JSONObject http_response;
List<String> user_string_list = new ArrayList<>();
ArrayAdapter<String> user_array_adapter;
int selected_user_position = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_or_edit_reminder);
get_view_resources();
setup_button_handlers();
setup_view_resources();
}
@Override
protected void onResume(){
super.onResume();
load_reminder();
}
private void load_reminder(){
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
String reminder_id = app_preferences.getString("selected_reminder", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
HttpUrl reqUrl = HttpUrl.parse(APIUrls.get_projects_url + "/" + project_id + "/reminders/" + reminder_id);
Request request = new Request.Builder().url(reqUrl).get().build();
mOkHttpClient.newCall(request).enqueue(load_reminder_callback);
}
private void delete_reminder(){
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
String reminder_id = app_preferences.getString("selected_reminder", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
HttpUrl reqUrl = HttpUrl.parse(APIUrls.get_projects_url + "/" + project_id + "/reminders/" + reminder_id);
Request request = new Request.Builder().url(reqUrl).delete().build();
mOkHttpClient.newCall(request).enqueue(delete_reminder_callback);
}
private void submit_edited_reminder(){
String title = new_edit_reminder_title_edit_text.getText().toString();
String reminder_date = new_edit_reminder_date_edit_text.getText().toString();
String text_content = new_edit_reminder_text_content_edit_text.getText().toString();
if(title.equals("")){
show_toast_text("Reminder Name Required...");
return;
}
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
String reminder_id = app_preferences.getString("selected_reminder", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
JSONObject json_body = new JSONObject();
try {
json_body.put("title", title);
json_body.put("reminder_date", reminder_date);
json_body.put("users_to_notify", new JSONArray(user_string_list));
json_body.put("text_content", text_content);
} catch(Exception e1){
e1.printStackTrace();
}
RequestBody body = RequestBody.create(JSON, json_body.toString());
HttpUrl reqUrl = HttpUrl.parse(APIUrls.post_projects_url + "/" + project_id + "/reminders/" + reminder_id);
Request request = new Request.Builder()
.url(reqUrl)
.put(body)
.build();
mOkHttpClient.newCall(request).enqueue(put_reminder_callback);
}
public Callback load_reminder_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Load project failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
try {
http_response = new JSONObject(callback_response);
String title = http_response.getString("title");
String reminder_date = http_response.getString("reminder_date");
String text_content = http_response.getString("text_content");
JSONArray users = http_response.getJSONArray("users_to_notify");
set_gui_elements(title, reminder_date, text_content, users);
}catch (JSONException e1) {
e1.printStackTrace();
}
}
};
public Callback delete_reminder_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Deleting reminder failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
show_toast_text("Reminder deleted successfully!");
Intent intent = new Intent(ReminderEditActivity.this, ReminderListingActivity.class);
startActivity(intent);
}
};
public Callback put_reminder_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
show_toast_text("Adding reminder failed!");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
show_toast_text("Reminder added successfully!");
Intent intent = new Intent(ReminderEditActivity.this, ReminderListingActivity.class);
startActivity(intent);
}
};
private void set_gui_elements(final String title, final String reminder_date, final String text_content, final JSONArray users){
runOnUiThread(new Runnable() {
@Override
public void run() {
new_edit_reminder_title_edit_text.setText(title);
new_edit_reminder_date_edit_text.setText(reminder_date);
new_edit_reminder_text_content_edit_text.setText(text_content);
for(int i = 0 ; i < users.length() ; i++){
try{
user_string_list.add(users.getString(i));
}catch (JSONException e1) {
e1.printStackTrace();
}
}
user_array_adapter.notifyDataSetChanged();
}
});
}
AdapterView.OnItemClickListener user_list_click_listener = new AdapterView.OnItemClickListener (){
@Override
public void onItemClick(AdapterView<?> parent, View current_list_item, int position, long id){
clear_row_background_colors();
current_list_item.setBackgroundColor(getColor(android.R.color.holo_orange_light));
selected_user_position = position;
new_edit_reminder_user_remove_button.setEnabled(true);
}
};
private void clear_row_background_colors(){
for(Integer i = 0 ; i < new_edit_reminder_user_list_view.getChildCount() ; i++){
new_edit_reminder_user_list_view.getChildAt(i).setBackground(null);
}
}
private void show_toast_text(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
}
private void get_view_resources(){
new_edit_reminder_title_edit_text = (EditText) findViewById(R.id.new_edit_reminder_title_edit_text);
new_edit_reminder_date_edit_text = (EditText) findViewById(R.id.new_edit_reminder_date_edit_text);
new_edit_reminder_text_content_edit_text = (EditText) findViewById(R.id.new_edit_reminder_text_content_edit_text);
new_edit_reminder_users_add_edit_text = (EditText) findViewById(R.id.new_edit_reminder_users_add_edit_text);
new_edit_reminder_add_edit_button = (Button) findViewById(R.id.new_edit_reminder_add_edit_button);
new_edit_reminder_delete_button = (Button) findViewById(R.id.new_edit_reminder_delete_button);
new_edit_reminder_user_add_button = (Button) findViewById(R.id.new_edit_reminder_user_add_button);
new_edit_reminder_user_remove_button = (Button) findViewById(R.id.new_edit_reminder_user_remove_button);
new_edit_reminder_user_list_view = (ListView) findViewById(R.id.new_edit_reminder_user_list_view);
}
private void setup_button_handlers(){
new_edit_reminder_add_edit_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
submit_edited_reminder();
}
});
new_edit_reminder_delete_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
delete_reminder();
}
});
new_edit_reminder_user_add_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
user_string_list.add(new_edit_reminder_users_add_edit_text.getText().toString());
user_array_adapter.notifyDataSetChanged();
new_edit_reminder_users_add_edit_text.setText("");
}
});
new_edit_reminder_user_remove_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
user_string_list.remove(selected_user_position);
user_array_adapter.notifyDataSetChanged();
clear_row_background_colors();
new_edit_reminder_user_remove_button.setEnabled(false);
}
});
}
private void setup_view_resources(){
new_edit_reminder_add_edit_button.setText("Update");
user_array_adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, user_string_list);
new_edit_reminder_user_list_view.setAdapter(user_array_adapter);
new_edit_reminder_user_list_view.setOnItemClickListener(user_list_click_listener);
}
}

View File

@@ -0,0 +1,232 @@
package com.example.corwinperren.cs496finalandroid;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
public class ReminderListingActivity extends AppCompatActivity {
TableLayout reminders_table_layout;
Button reminders_list_home_button;
Button new_reminder_button;
Button edit_reminder_button;
Button view_reminder_button;
JSONArray http_response;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reminder_list);
get_view_resources();
setup_button_handlers();
}
@Override
protected void onResume(){
super.onResume();
load_reminders();
}
private void load_reminders(){
clear_reminders();
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
HttpUrl reqUrl = HttpUrl.parse(APIUrls.get_projects_url + "/" + project_id + "/reminders");
Request request = new Request.Builder().url(reqUrl).get().build();
mOkHttpClient.newCall(request).enqueue(load_reminders_callback);
}
public Callback load_reminders_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
try {
http_response = new JSONArray(callback_response);
Integer num_reminders = http_response.length();
if(num_reminders == 0){
set_buttons_enabled(false);
return;
}
for (Integer index = 0 ; index < num_reminders ; index++){
JSONObject current_reminder = http_response.getJSONObject(index);
String title = current_reminder.getString("title");
String reminder_date = current_reminder.getString("reminder_date");
String reminder_id = current_reminder.getString("id");
add_row_to_table(title, reminder_date, reminder_id);
}
}catch (JSONException e1) {
e1.printStackTrace();
}
select_first_reminder();
}
private void add_row_to_table(final String title, final String reminder_date, final String reminder_id){
runOnUiThread(new Runnable() {
@Override
public void run() {
TableRow newRow = new TableRow(ReminderListingActivity.this);
TextView titleTextView = new TextView(ReminderListingActivity.this);
TextView reminderDateTextVew = new TextView(ReminderListingActivity.this);
titleTextView.setText(title);
if(!reminder_date.equals("null")) {
reminderDateTextVew.setText(reminder_date);
}
newRow.addView(titleTextView);
newRow.addView(reminderDateTextVew);
newRow.setTag(reminder_id);
newRow.setClickable(true);
newRow.setOnClickListener(row_click_listener);
reminders_table_layout.addView(newRow, new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT));
}
});
}
};
View.OnClickListener row_click_listener = new View.OnClickListener(){
@Override
public void onClick(View current_row){
clear_row_background_colors();
current_row.setBackgroundColor(getColor(android.R.color.holo_orange_light));
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
app_preferences.edit().putString("selected_reminder", current_row.getTag().toString()).apply();
set_buttons_enabled(true);
}
};
private void set_buttons_enabled(final boolean enabled){
runOnUiThread(new Runnable() {
@Override
public void run() {
edit_reminder_button.setEnabled(enabled);
view_reminder_button.setEnabled(enabled);
}
});
}
private void select_first_reminder(){
runOnUiThread(new Runnable() {
@Override
public void run() {
if(reminders_table_layout.getChildCount() > 1){
TableRow row = (TableRow) reminders_table_layout.getChildAt(1);
row.performClick();
}
}
});
}
private void clear_row_background_colors(){
for(Integer i = 0 ; i < reminders_table_layout.getChildCount() ; i++){
TableRow row = (TableRow) reminders_table_layout.getChildAt(i);
row.setBackground(null);
}
}
private void clear_reminders(){
int numTableRows = reminders_table_layout.getChildCount();
if (numTableRows > 1){
reminders_table_layout.removeViews(1, numTableRows - 1);
}
}
private void get_view_resources(){
reminders_table_layout = (TableLayout) findViewById(R.id.reminders_table_layout);
reminders_list_home_button = (Button) findViewById(R.id.reminders_list_home_button);
new_reminder_button = (Button) findViewById(R.id.new_reminder_button);
edit_reminder_button = (Button) findViewById(R.id.edit_reminder_button);
view_reminder_button = (Button) findViewById(R.id.view_reminder_button);
}
private void setup_button_handlers(){
reminders_list_home_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(ReminderListingActivity.this, MainActivity.class);
startActivity(intent);
}
});
new_reminder_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(ReminderListingActivity.this, NewReminderActivity.class);
startActivity(intent);
}
});
edit_reminder_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(ReminderListingActivity.this, ReminderEditActivity.class);
startActivity(intent);
}
});
view_reminder_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent(ReminderListingActivity.this, ReminderViewActivity.class);
startActivity(intent);
}
});
}
}

View File

@@ -0,0 +1,135 @@
package com.example.corwinperren.cs496finalandroid;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class ReminderViewActivity extends AppCompatActivity {
TextView view_reminder_title_text_view;
TextView view_reminder_date_text_view;
TextView view_reminder_content_text_view;
ListView view_reminder_users_list_view;
JSONObject http_response;
List<String> user_string_list = new ArrayList<>();
ArrayAdapter<String> user_array_adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_reminder);
get_view_resources();
setup_view_resources();
}
@Override
protected void onResume(){
super.onResume();
load_reminder();
}
private void load_reminder(){
user_array_adapter.clear();
SharedPreferences app_preferences = getSharedPreferences("app_prefs", MODE_PRIVATE);
String project_id = app_preferences.getString("selected_project", null);
String reminder_id = app_preferences.getString("selected_reminder", null);
OkHttpClient mOkHttpClient = new OkHttpClient();
HttpUrl reqUrl = HttpUrl.parse(APIUrls.get_projects_url + "/" + project_id + "/reminders/" + reminder_id);
Request request = new Request.Builder().url(reqUrl).get().build();
mOkHttpClient.newCall(request).enqueue(load_reminders_callback);
}
public Callback load_reminders_callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String callback_response = response.body().string();
Log.d(MainActivity.TAG, callback_response);
try {
http_response = new JSONObject(callback_response);
String title = http_response.getString("title");
String reminder_date = http_response.getString("reminder_date");
String text_content = http_response.getString("text_content");
JSONArray users = http_response.getJSONArray("users_to_notify");
set_gui_elements(title, reminder_date, text_content, users);
}catch (JSONException e1) {
e1.printStackTrace();
}
}
};
private void set_gui_elements(final String title, final String reminder_date, final String text_content, final JSONArray users){
runOnUiThread(new Runnable() {
@Override
public void run() {
view_reminder_title_text_view.setText(title);
view_reminder_date_text_view.setText(reminder_date);
view_reminder_content_text_view.setText(text_content);
for(int i = 0 ; i < users.length() ; i++){
try{
user_string_list.add(users.getString(i));
}catch (JSONException e1) {
e1.printStackTrace();
}
}
user_array_adapter.notifyDataSetChanged();
}
});
}
private void setup_view_resources(){
user_array_adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, user_string_list);
view_reminder_users_list_view.setAdapter(user_array_adapter);
}
private void get_view_resources(){
view_reminder_title_text_view = (TextView) findViewById(R.id.view_reminder_title_text_view);
view_reminder_date_text_view = (TextView) findViewById(R.id.view_reminder_date_text_view);
view_reminder_content_text_view = (TextView) findViewById(R.id.view_reminder_content_text_view);
view_reminder_users_list_view = (ListView) findViewById(R.id.view_reminder_users_list_view);
}
}

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.corwinperren.cs496finalandroid.MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Projects"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:layout_width="368dp"
android:layout_height="414dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/textView"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:id="@+id/scrollView2"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/edit_project_button"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0">
<TableLayout
android:id="@+id/projects_table_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="3"
android:choiceMode="singleChoice">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView5"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:text="Name"
android:textAlignment="viewStart"
android:textColor="@android:color/black"
android:textStyle="bold" />
<TextView
android:id="@+id/textView4"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:text="Language"
android:textAlignment="viewStart"
android:textColor="@android:color/black"
android:textStyle="bold" />
<TextView
android:id="@+id/textView2"
android:layout_width="110dp"
android:layout_height="wrap_content"
android:text="Contributors"
android:textAlignment="viewStart"
android:textColor="@android:color/black"
android:textStyle="bold" />
</TableRow>
</TableLayout>
</ScrollView>
<Button
android:id="@+id/new_project_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="New"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/edit_project_button" />
<Button
android:id="@+id/edit_project_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="Edit"
android:enabled="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@+id/edit_reminders_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="0dp"
android:layout_marginStart="8dp"
android:text="Reminders"
android:enabled="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/edit_project_button"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.516" />
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="Contributors"
android:textAlignment="center"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/project_language_edit_text" />
<EditText
android:id="@+id/project_name_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:ems="10"
android:hint="Project Name"
android:inputType="textPersonName"
app:layout_constraintBottom_toBottomOf="@+id/project_submit_update_button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/project_submit_update_button"
app:layout_constraintVertical_bias="0.333" />
<EditText
android:id="@+id/project_language_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Project Language"
android:inputType="textPersonName"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/project_delete_button"
app:layout_constraintBottom_toBottomOf="@+id/project_delete_button"
android:layout_marginStart="8dp" />
<EditText
android:id="@+id/contributor_name_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Contributor Name"
android:inputType="textPersonName"
android:layout_marginTop="7dp"
app:layout_constraintTop_toBottomOf="@+id/textView8"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@+id/project_submit_update_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" />
<Button
android:id="@+id/contributor_add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add "
app:layout_constraintLeft_toLeftOf="@+id/contributor_name_edit_text"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/contributor_name_edit_text" />
<Button
android:id="@+id/project_delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/project_submit_update_button"
android:layout_marginEnd="8dp" />
<Button
android:id="@+id/contributor_remove_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginRight="0dp"
android:layout_marginTop="8dp"
android:text="Remove"
android:enabled="false"
app:layout_constraintBottom_toTopOf="@+id/contributor_list_view"
app:layout_constraintRight_toRightOf="@+id/contributor_name_edit_text"
app:layout_constraintTop_toBottomOf="@+id/contributor_name_edit_text" />
<ListView
android:id="@+id/contributor_list_view"
android:layout_width="368dp"
android:layout_height="246dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:headerDividersEnabled="false"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contributor_add_button"
app:layout_constraintVertical_bias="0.0" />
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/new_edit_reminder_title_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:ems="10"
android:hint="Title"
android:inputType="textPersonName"
app:layout_constraintBottom_toBottomOf="@+id/new_edit_reminder_add_edit_button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/new_edit_reminder_add_edit_button" />
<EditText
android:id="@+id/new_edit_reminder_date_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:ems="10"
android:hint="Reminder Date"
android:inputType="textPersonName"
app:layout_constraintBottom_toBottomOf="@+id/new_edit_reminder_delete_button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/new_edit_reminder_delete_button" />
<Button
android:id="@+id/new_edit_reminder_add_edit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="Update"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/new_edit_reminder_delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="Delete"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/new_edit_reminder_add_edit_button" />
<TextView
android:id="@+id/textView16"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Users To Notify"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/new_edit_reminder_text_content_edit_text" />
<EditText
android:id="@+id/new_edit_reminder_users_add_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="Name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView16" />
<Button
android:id="@+id/new_edit_reminder_user_add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Add"
app:layout_constraintLeft_toLeftOf="@+id/new_edit_reminder_users_add_edit_text"
app:layout_constraintTop_toBottomOf="@+id/new_edit_reminder_users_add_edit_text" />
<Button
android:id="@+id/new_edit_reminder_user_remove_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Remove"
app:layout_constraintRight_toRightOf="@+id/new_edit_reminder_users_add_edit_text"
app:layout_constraintTop_toBottomOf="@+id/new_edit_reminder_users_add_edit_text" />
<EditText
android:id="@+id/new_edit_reminder_text_content_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textMultiLine"
android:lines="4"
android:layout_marginLeft="8dp"
android:hint="Reminder Text"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/new_edit_reminder_date_edit_text"
android:layout_marginStart="8dp" />
<ListView
android:id="@+id/new_edit_reminder_user_list_view"
android:layout_width="368dp"
android:layout_height="139dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/new_edit_reminder_user_add_button"
app:layout_constraintVertical_bias="0.0" />
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="17dp"
android:text="Reminders"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginStart="8dp" />
<Button
android:id="@+id/new_reminder_button"
android:layout_width="88dp"
android:layout_height="wrap_content"
android:text="New"
app:layout_constraintRight_toLeftOf="@+id/edit_reminder_button"
app:layout_constraintLeft_toRightOf="@+id/reminders_list_home_button"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" />
<Button
android:id="@+id/edit_reminder_button"
android:layout_width="88dp"
android:layout_height="48dp"
android:text="Edit"
app:layout_constraintRight_toLeftOf="@+id/view_reminder_button"
app:layout_constraintLeft_toRightOf="@+id/new_reminder_button"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" />
<Button
android:id="@+id/view_reminder_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="View"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="@+id/edit_reminder_button"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" />
<Button
android:id="@+id/reminders_list_home_button"
android:layout_width="88dp"
android:layout_height="48dp"
android:text="Home"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/new_reminder_button"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" />
<ScrollView
android:id="@+id/scrollView3"
android:layout_width="368dp"
android:layout_height="410dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView6">
<TableLayout
android:id="@+id/reminders_table_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="2">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView7"
android:layout_width="215dp"
android:layout_height="wrap_content"
android:text="Title"
android:textColor="@android:color/black"
android:textStyle="bold" />
<TextView
android:id="@+id/textView3"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="Reminder Date"
android:textColor="@android:color/black"
android:textStyle="bold" />
</TableRow>
</TableLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Title"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Reminder Date"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView9" />
<TextView
android:id="@+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Content"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView10" />
<TextView
android:id="@+id/view_reminder_title_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="@android:color/black"
app:layout_constraintLeft_toLeftOf="@+id/view_reminder_date_text_view"
app:layout_constraintTop_toTopOf="@+id/textView9" />
<TextView
android:id="@+id/view_reminder_date_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="TextView"
android:textColor="@android:color/black"
app:layout_constraintLeft_toRightOf="@+id/textView10"
app:layout_constraintTop_toTopOf="@+id/textView10" />
<TextView
android:id="@+id/view_reminder_content_text_view"
android:layout_width="268dp"
android:layout_height="59dp"
android:layout_marginTop="1dp"
android:lines="4"
android:text="TextView"
android:textColor="@android:color/black"
app:layout_constraintLeft_toLeftOf="@+id/view_reminder_date_text_view"
app:layout_constraintTop_toTopOf="@+id/textView11" />
<TextView
android:id="@+id/textView15"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Users To Notify"
android:textColor="@android:color/black"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@+id/view_reminder_content_text_view"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent" />
<ListView
android:id="@+id/view_reminder_users_list_view"
android:layout_width="368dp"
android:layout_height="345dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView15"
app:layout_constraintVertical_bias="0.0" />
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">CS496 Project Reminder Tool</string>
</resources>

View File

@@ -0,0 +1,11 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@@ -0,0 +1,17 @@
from google.appengine.ext import ndb
class Project(ndb.Model):
name = ndb.StringProperty(required=True)
language = ndb.StringProperty()
contributors = ndb.StringProperty(repeated=True)
reminders = ndb.StringProperty(repeated=True)
id = ndb.StringProperty()
class ProjectReminder(ndb.Model):
title = ndb.StringProperty(required=True)
reminder_date = ndb.StringProperty()
users_to_notify = ndb.StringProperty(repeated=True)
text_content = ndb.StringProperty()
id = ndb.StringProperty()

View File

@@ -0,0 +1,348 @@
import webapp2
import json
from google.appengine.ext import ndb
from EntitiesCore import Project, ProjectReminder
class RestProjectHandler(webapp2.RequestHandler):
NEW_PROJECT_REQUIRED_POST_VALUES = ["name"]
PROJECT_LIST_COLUMNS_TO_STRIP = ["reminders"]
AVAILABLE_KEYS_FOR_PUT_AND_PATCH = ["name", "language", "contributors"]
def get(self, project_id=None):
self.get_project_by_id(project_id=project_id) if project_id else self.get_all_projects()
def post(self):
self.make_new_project()
def delete(self, project_id=None):
if project_id:
self.delete_project_by_id(project_id=project_id)
else:
self.error(404)
def put(self, project_id=None):
if project_id:
self.put_new_values_in_project_by_id(project_id=project_id)
else:
self.error(404)
def patch(self, project_id=None):
if project_id:
self.patch_new_value_in_project_by_id(project_id=project_id)
else:
self.error(404)
def get_all_projects(self):
projects = Project.query().fetch()
output_array = []
for project in projects:
temp_dict = project.to_dict()
temp_dict = self.strip_key_value_pairs_from_dict(temp_dict, self.PROJECT_LIST_COLUMNS_TO_STRIP)
output_array.append(temp_dict)
self.response.write(json.dumps(output_array))
def get_project_by_id(self, project_id):
entity = get_ndb_entity_from_id(project_id)
if not entity:
self.error(404)
return
temp_dict = entity.to_dict()
temp_dict = self.strip_key_value_pairs_from_dict(temp_dict, self.PROJECT_LIST_COLUMNS_TO_STRIP)
self.response.write(json.dumps(temp_dict))
def make_new_project(self):
parsed_json = json.loads(self.request.body)
if not self.NEW_PROJECT_REQUIRED_POST_VALUES <= set(parsed_json):
self.error(404)
return
name = get_value_from_dict_or_none("name", parsed_json)
language = get_value_from_dict_or_none("language", parsed_json)
contributors = get_value_from_dict_or_none("contributors", parsed_json)
new_project = Project(name=name, language=language, contributors=contributors)
new_project.put()
new_project.id = new_project.key.urlsafe()
new_project.put()
temp_dict = new_project.to_dict()
temp_dict = self.strip_key_value_pairs_from_dict(temp_dict, self.PROJECT_LIST_COLUMNS_TO_STRIP)
self.response.write(json.dumps(temp_dict))
def delete_project_by_id(self, project_id):
entity = get_ndb_entity_from_id(project_id)
if not entity:
self.error(404)
return
project_dict = entity.to_dict()
reminder_ids = get_value_from_dict_or_none("reminders", project_dict)
for reminder_id in reminder_ids:
reminder_entity = get_ndb_entity_from_id(reminder_id)
reminder_entity.key.delete()
entity.key.delete()
def put_new_values_in_project_by_id(self, project_id):
project_entity = get_ndb_entity_from_id(project_id)
if not project_entity:
self.error(404)
return
parsed_json = json.loads(self.request.body)
if not len(parsed_json):
self.error(404)
return
temp_dict = get_dict_with_valid_key_value_pairs(parsed_json, self.AVAILABLE_KEYS_FOR_PUT_AND_PATCH)
project_entity.populate(**temp_dict)
project_entity.put()
def patch_new_value_in_project_by_id(self, project_id):
project_entity = get_ndb_entity_from_id(project_id)
if not project_entity:
self.error(404)
return
parsed_json = json.loads(self.request.body)
if len(parsed_json) != 1:
self.error(404)
return
key, _ = parsed_json.items()[0]
if key in self.AVAILABLE_KEYS_FOR_PUT_AND_PATCH:
project_entity.populate(**parsed_json)
project_entity.put()
else:
self.error(404)
return
@staticmethod
def strip_key_value_pairs_from_dict(input_dict, to_strip):
for key in to_strip:
if key in input_dict:
del input_dict[key]
return input_dict
class RestProjectReminderHandler(webapp2.RequestHandler):
NEW_REMINDER_REQUIRED_POST_VALUES = ["title"]
AVAILABLE_KEYS_FOR_PUT_AND_PATCH = ["title", "reminder_date", "users_to_notify", "text_content"]
def get(self, project_id=None, reminder_id=None):
if project_id and reminder_id:
self.get_reminder_by_ids(project_id=project_id, reminder_id=reminder_id)
elif project_id:
self.get_all_reminders_for_project(project_id=project_id)
else:
self.error(404)
def post(self, project_id=None):
if project_id:
self.make_new_project_reminder(project_id=project_id)
else:
self.error(404)
def delete(self, project_id=None, reminder_id=None):
if project_id and reminder_id:
self.delete_reminder_by_ids(project_id=project_id, reminder_id=reminder_id)
else:
self.error(404)
def put(self, project_id=None, reminder_id=None):
if project_id and reminder_id:
self.put_new_values_in_reminder_by_id(reminder_id=reminder_id)
else:
self.error(404)
def patch(self, project_id=None, reminder_id=None):
if project_id and reminder_id:
self.patch_new_value_in_reminder_by_id(reminder_id=reminder_id)
else:
self.error(404)
def get_all_reminders_for_project(self, project_id):
project_entity = get_ndb_entity_from_id(project_id) # type: Project
if not project_entity:
self.error(404)
return
project_dict = project_entity.to_dict()
reminder_ids = get_value_from_dict_or_none("reminders", project_dict)
output_reminder_array = []
for reminder_id in reminder_ids:
reminder_entity = get_ndb_entity_from_id(reminder_id)
output_reminder_array.append(reminder_entity.to_dict())
self.response.write(json.dumps(output_reminder_array))
def get_reminder_by_ids(self, project_id, reminder_id):
project_entity = get_ndb_entity_from_id(project_id) # type: Project
if not project_entity:
self.error(404)
return
project_dict = project_entity.to_dict()
reminder_ids = get_value_from_dict_or_none("reminders", project_dict)
if reminder_id not in reminder_ids:
self.error(404)
return
reminder_entity = get_ndb_entity_from_id(reminder_id)
self.response.write(json.dumps(reminder_entity.to_dict()))
def make_new_project_reminder(self, project_id):
parsed_json = json.loads(self.request.body)
# Check if the request has bare minimum number of required values
if not self.NEW_REMINDER_REQUIRED_POST_VALUES <= set(parsed_json):
self.error(404)
return
# Check if the project exists
entity = get_ndb_entity_from_id(project_id) # type: Project
if not entity:
self.error(404)
return
title = get_value_from_dict_or_none("title", parsed_json)
reminder_date = get_value_from_dict_or_none("reminder_date", parsed_json)
users_to_notify = get_value_from_dict_or_none("users_to_notify", parsed_json)
text_content = get_value_from_dict_or_none("text_content", parsed_json)
new_project_reminder = ProjectReminder(title=title, reminder_date=reminder_date, users_to_notify=users_to_notify, text_content=text_content)
new_project_reminder.put()
new_project_reminder.id = new_project_reminder.key.urlsafe()
new_project_reminder.put()
entity.reminders.append(new_project_reminder.id)
entity.put()
self.response.write(json.dumps(new_project_reminder.to_dict()))
def delete_reminder_by_ids(self, project_id, reminder_id):
project_entity = get_ndb_entity_from_id(project_id) # type: Project
if not project_entity:
self.error(404)
return
project_dict = project_entity.to_dict()
reminder_ids = get_value_from_dict_or_none("reminders", project_dict)
if reminder_id not in reminder_ids:
self.error(404)
return
reminder_entity = get_ndb_entity_from_id(reminder_id)
reminder_entity.key.delete()
reminder_id_index_in_project = project_entity.reminders.index(reminder_id)
project_entity.reminders.pop(reminder_id_index_in_project)
project_entity.put()
def put_new_values_in_reminder_by_id(self, reminder_id):
reminder_entity = get_ndb_entity_from_id(reminder_id)
if not reminder_entity:
self.error(404)
return
parsed_json = json.loads(self.request.body)
if not len(parsed_json):
self.error(404)
return
temp_dict = get_dict_with_valid_key_value_pairs(parsed_json, self.AVAILABLE_KEYS_FOR_PUT_AND_PATCH)
reminder_entity.populate(**temp_dict)
reminder_entity.put()
def patch_new_value_in_reminder_by_id(self, reminder_id):
reminder_entity = get_ndb_entity_from_id(reminder_id)
if not reminder_entity:
self.error(404)
return
parsed_json = json.loads(self.request.body)
if len(parsed_json) != 1:
self.error(404)
return
key, _ = parsed_json.items()[0]
if key in self.AVAILABLE_KEYS_FOR_PUT_AND_PATCH:
reminder_entity.populate(**parsed_json)
reminder_entity.put()
else:
self.error(404)
return
def get_dict_with_valid_key_value_pairs(input_dict, valid_values):
output_dict = {}
for dict_key in input_dict:
if dict_key in valid_values:
output_dict[dict_key] = input_dict[dict_key]
return output_dict
def get_value_from_dict_or_none(value, dict_to_check):
return dict_to_check[value] if value in dict_to_check else None
def get_ndb_entity_from_id(id_to_find):
key = ndb.Key(urlsafe=id_to_find)
return key.get()

View File

@@ -0,0 +1,16 @@
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
- url: .*
script: main.app
libraries:
- name: webapp2
version: "2.5.2"

View File

@@ -0,0 +1,18 @@
indexes:
# AUTOGENERATED
# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run. If you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED"). If you want to manage some indexes
# manually, move them above the marker line. The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.
- kind: Project
properties:
- name: contributors
- name: id
- name: language
- name: name

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python
import webapp2
from RestAPIHandlersCore import RestProjectHandler, RestProjectReminderHandler
allowed_methods = webapp2.WSGIApplication.allowed_methods
new_allowed_methods = allowed_methods.union(('PATCH',))
webapp2.WSGIApplication.allowed_methods = new_allowed_methods
app = webapp2.WSGIApplication([
webapp2.Route("/projects", RestProjectHandler, name="project-handler"),
webapp2.Route("/projects/<project_id>", RestProjectHandler, name="project-handler"),
webapp2.Route("/projects/<project_id>/reminders", RestProjectReminderHandler, name="reminder-handler"),
webapp2.Route("/projects/<project_id>/reminders/<reminder_id>", RestProjectReminderHandler, name="reminder-handler")
], debug=True)