Merge pull request #117 from ClaytonWWilson/intra-list-ordering

Intra list ordering
This commit is contained in:
Nathan Merz 2020-11-20 15:54:38 -05:00 committed by GitHub
commit b1184b1bf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 181 additions and 31 deletions

View File

@ -9,14 +9,16 @@ public class List {
long lastUpdated; long lastUpdated;
ArrayList<ItemEntry> entries; ArrayList<ItemEntry> entries;
boolean shared; boolean shared;
Integer uiPosition;
public List(ResultSet listRow, boolean shared) throws SQLException { public List(ResultSet listRow, boolean shared, Integer uiPosition) throws SQLException {
itemID = listRow.getInt("listID"); itemID = listRow.getInt("listID");
name = listRow.getString("name"); name = listRow.getString("name");
owner = listRow.getString("owner"); owner = listRow.getString("owner");
lastUpdated = listRow.getTimestamp("lastUpdated").toInstant().toEpochMilli(); lastUpdated = listRow.getTimestamp("lastUpdated").toInstant().toEpochMilli();
entries = new ArrayList<>(); entries = new ArrayList<>();
this.shared = shared; this.shared = shared;
this.uiPosition = uiPosition;
} }
@Override @Override
@ -27,6 +29,8 @@ public class List {
", owner='" + owner + '\'' + ", owner='" + owner + '\'' +
", lastUpdated=" + lastUpdated + ", lastUpdated=" + lastUpdated +
", entries=" + entries + ", entries=" + entries +
", shared=" + shared +
", uiPosition=" + uiPosition +
'}'; '}';
} }
@ -70,6 +74,13 @@ public class List {
this.shared = shared; this.shared = shared;
} }
public Integer getUiPosition() {
return uiPosition;
}
public void setUiPosition(Integer uiPosition) {
this.uiPosition = uiPosition;
public ItemEntry[] getEntries() { public ItemEntry[] getEntries() {
return entries.toArray(new ItemEntry[entries.size()]); return entries.toArray(new ItemEntry[entries.size()]);
} }

View File

@ -9,7 +9,8 @@ public class ListAdder implements CallHandler {
private String cognitoID; private String cognitoID;
private final String LIST_CREATE = "INSERT INTO List (name, owner, lastUpdated) VALUES (?, ?, ?);"; private final String LIST_CREATE = "INSERT INTO List (name, owner, lastUpdated) VALUES (?, ?, ?);";
private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID, permissionLevel) VALUES(?, ?, ?);"; private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID, permissionLevel, uiPosition) VALUES(?, ?, ?, ?);";
private final String UI_POSITION_CHECK = "SELECT Max(uiPosition) as maxUIPosition FROM ListSharee WHERE userID = ?;";
public ListAdder(Connection connection, String cognitoID) { public ListAdder(Connection connection, String cognitoID) {
this.connection = connection; this.connection = connection;
@ -17,9 +18,17 @@ public class ListAdder implements CallHandler {
} }
public Object conductAction(Map<String, Object> bodyMap, HashMap<String, String> queryString, String cognitoID) throws SQLException { public Object conductAction(Map<String, Object> bodyMap, HashMap<String, String> queryString, String cognitoID) throws SQLException {
PreparedStatement statement = connection.prepareStatement(LIST_CREATE, Statement.RETURN_GENERATED_KEYS);
String listName = bodyMap.get("name").toString();//Needs safe checking String listName = bodyMap.get("name").toString();//Needs safe checking
PreparedStatement uiPositionCheck = connection.prepareStatement(UI_POSITION_CHECK);
uiPositionCheck.setString(1, cognitoID);
ResultSet uiPositionCheckRS = uiPositionCheck.executeQuery();
int nextPosition = 1;
if (uiPositionCheckRS.next()) {
nextPosition = uiPositionCheckRS.getInt("maxUIPosition") + 1;
}
PreparedStatement statement = connection.prepareStatement(LIST_CREATE, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, listName); statement.setString(1, listName);
statement.setString(2, cognitoID); statement.setString(2, cognitoID);
statement.setTimestamp(3, Timestamp.from(Instant.now())); statement.setTimestamp(3, Timestamp.from(Instant.now()));
@ -32,6 +41,7 @@ public class ListAdder implements CallHandler {
accessGrant.setInt(1, newID); accessGrant.setInt(1, newID);
accessGrant.setString(2, cognitoID); accessGrant.setString(2, cognitoID);
accessGrant.setInt(3, ListPermissions.getAll()); accessGrant.setInt(3, ListPermissions.getAll());
accessGrant.setInt(4, nextPosition);
System.out.println(accessGrant); System.out.println(accessGrant);
accessGrant.executeUpdate(); accessGrant.executeUpdate();
connection.commit(); connection.commit();

View File

@ -12,7 +12,7 @@ public class ListGetter implements CallHandler{
private final String cognitoID; private final String cognitoID;
private final String GET_LIST = "SELECT * FROM List WHERE listID = ?;"; private final String GET_LIST = "SELECT * FROM List WHERE listID = ?;";
private final String GET_LISTS = "SELECT listID FROM ListSharee WHERE userID = ?;"; private final String GET_LISTS = "SELECT listID FROM ListSharee WHERE userID = ? ORDER BY uiPosition;";
private final String SHARE_CHECK = "SELECT * FROM ListSharee WHERE listID = ?;"; private final String SHARE_CHECK = "SELECT * FROM ListSharee WHERE listID = ?;";
private final String GET_ENTRIES = "SELECT * FROM ListProduct WHERE listID = ?;"; private final String GET_ENTRIES = "SELECT * FROM ListProduct WHERE listID = ?;";
@ -42,6 +42,7 @@ public class ListGetter implements CallHandler{
ResultSet accessResults = checkAccess.executeQuery(); ResultSet accessResults = checkAccess.executeQuery();
int sharees = 0; int sharees = 0;
boolean verifiedAccess = false; boolean verifiedAccess = false;
int uiPosition = 1;
while ((sharees < 2 && accessResults.next()) || !verifiedAccess) { while ((sharees < 2 && accessResults.next()) || !verifiedAccess) {
int permissionLevel = accessResults.getInt("permissionLevel"); int permissionLevel = accessResults.getInt("permissionLevel");
if (accessResults.getString("userID").equals(cognitoID)) { if (accessResults.getString("userID").equals(cognitoID)) {
@ -49,6 +50,7 @@ public class ListGetter implements CallHandler{
if (!ListPermissions.hasPermission(permissionLevel, "Read")) { if (!ListPermissions.hasPermission(permissionLevel, "Read")) {
throw new AccessControlException("User " + cognitoID + " does not have permission to read list " + id); throw new AccessControlException("User " + cognitoID + " does not have permission to read list " + id);
} }
uiPosition = accessResults.getInt("uiPosition");
} }
if (permissionLevel > 0) { if (permissionLevel > 0) {
sharees++; sharees++;
@ -64,7 +66,7 @@ public class ListGetter implements CallHandler{
ResultSet getListResults = getList.executeQuery(); ResultSet getListResults = getList.executeQuery();
getListResults.first(); getListResults.first();
System.out.println(getListResults); System.out.println(getListResults);
List retrievedList = new List(getListResults, shared); List retrievedList = new List(getListResults, shared, uiPosition);
System.out.println(retrievedList); System.out.println(retrievedList);
PreparedStatement getListEntries = connection.prepareStatement(GET_ENTRIES); PreparedStatement getListEntries = connection.prepareStatement(GET_ENTRIES);
getListEntries.setInt(1, id); getListEntries.setInt(1, id);

View File

@ -0,0 +1,70 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class ListRepositionActor implements CallHandler {
private Connection connection;
private String cognitoID;
public ListRepositionActor(Connection connection, String cognitoID) {
this.connection = connection;
this.cognitoID = cognitoID;
}
final private String GET_PRIOR_POSITION = "SELECT uiPosition FROM ListSharee WHERE userID = ? AND listID = ?;";
final private String SET_NEW_POSITION = "UPDATE ListSharee SET uiPosition = ? WHERE userID = ? AND listID = ?;";
final private String DECREMENT_HIGHER_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition - 1 WHERE uiPosition > ? AND userID = ?;";
final private String INCREMENT_GEQ_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition + 1 WHERE uiPosition >= ? AND userID = ?;";
public Object conductAction(Map<String, Object> bodyMap, HashMap<String, String> queryString, String cognitoID) throws SQLException {
Integer listID = (Integer) bodyMap.get("listID");
Integer newPosition = (Integer) bodyMap.get("newPosition");
PreparedStatement getPriorPosition = connection.prepareStatement(GET_PRIOR_POSITION);
getPriorPosition.setString(1, cognitoID);
getPriorPosition.setInt(2, listID);
ResultSet priorPositionRS = getPriorPosition.executeQuery();
if (!priorPositionRS.next()) {
throw new IllegalArgumentException("Bad listID for user");
}
Integer priorPosition = priorPositionRS.getInt("uiPosition");
PreparedStatement openNewPosition = connection.prepareStatement(INCREMENT_GEQ_POSITIONS);
if (newPosition.equals(priorPosition)) {
return null;
}
if (newPosition < priorPosition) {
openNewPosition.setInt(1, newPosition);
} else {
openNewPosition.setInt(1, newPosition + 1);
}
openNewPosition.setString(2, cognitoID);
System.out.println(openNewPosition);
openNewPosition.executeUpdate();
PreparedStatement fillPriorPosition = connection.prepareStatement(DECREMENT_HIGHER_POSITIONS);
fillPriorPosition.setInt(1, priorPosition);
fillPriorPosition.setString(2, cognitoID);
System.out.println(fillPriorPosition);
fillPriorPosition.executeUpdate();
PreparedStatement setNewPosition = connection.prepareStatement(SET_NEW_POSITION);
setNewPosition.setInt(1, newPosition);
setNewPosition.setString(2, cognitoID);
setNewPosition.setInt(3, listID);
System.out.println(setNewPosition);
setNewPosition.executeUpdate();
connection.commit();
return null;
}
}

View File

@ -0,0 +1,11 @@
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import java.util.Map;
public class ListRepositionPUT implements RequestHandler<Map<String,Object>, Object> {
public Object handleRequest(Map<String, Object> inputMap, Context unfilled) {
return BasicHandler.handleRequest(inputMap, unfilled, ListRepositionActor.class);
}
}

View File

@ -22,9 +22,9 @@ public class ListSharer implements CallHandler {
} }
final private String CHECK_ACCESS = "SELECT * from ListSharee WHERE listID = ? AND userID = ?;"; final private String CHECK_ACCESS = "SELECT * from ListSharee WHERE listID = ? AND userID = ?;";
private final String UI_POSITION_CHECK = "SELECT Max(uiPosition) as maxUIPosition FROM ListSharee WHERE userID = ?;";
final private String SHARE_LIST = "INSERT INTO ListSharee(listID, userID, permissionLevel, uiPosition) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE permissionLevel = ?;"; final private String SHARE_LIST = "INSERT INTO ListSharee(listID, userID, permissionLevel, uiPosition) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE permissionLevel = ?;";
public Object conductAction(Map<String, Object> bodyMap, HashMap<String, String> queryString, String cognitoID) throws SQLException { public Object conductAction(Map<String, Object> bodyMap, HashMap<String, String> queryString, String cognitoID) throws SQLException {
PreparedStatement checkAccess = connection.prepareStatement(CHECK_ACCESS); PreparedStatement checkAccess = connection.prepareStatement(CHECK_ACCESS);
Integer listID = Integer.parseInt(bodyMap.get("listID").toString()); Integer listID = Integer.parseInt(bodyMap.get("listID").toString());
@ -63,12 +63,23 @@ public class ListSharer implements CallHandler {
// throw new InputMismatchException("The specified user already has access"); // throw new InputMismatchException("The specified user already has access");
// } // }
PreparedStatement uiPositionCheck = connection.prepareStatement(UI_POSITION_CHECK);
uiPositionCheck.setString(1, shareWithSub);
System.out.println(uiPositionCheck);
ResultSet uiPositionCheckRS = uiPositionCheck.executeQuery();
int nextPosition = 1;
if (uiPositionCheckRS.next()) {
nextPosition = uiPositionCheckRS.getInt("maxUIPosition") + 1;
}
PreparedStatement shareList = connection.prepareStatement(SHARE_LIST); PreparedStatement shareList = connection.prepareStatement(SHARE_LIST);
shareList.setInt(1, listID); shareList.setInt(1, listID);
shareList.setString(2, shareWithSub); shareList.setString(2, shareWithSub);
Integer permissionLevel = Integer.parseInt(bodyMap.get("permissionLevel").toString()); Integer permissionLevel = Integer.parseInt(bodyMap.get("permissionLevel").toString());
shareList.setInt(3, permissionLevel); shareList.setInt(3, permissionLevel);
shareList.setInt(4, permissionLevel); shareList.setInt(4, nextPosition);
shareList.setInt(5, permissionLevel);
System.out.println(shareList);
shareList.executeUpdate(); shareList.executeUpdate();
connection.commit(); connection.commit();
return null; return null;

View File

@ -1,27 +1,15 @@
package com.example.listify; package com.example.listify;
import android.app.Dialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.view.View;
import com.amplifyframework.auth.AuthException; import android.widget.*;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.example.listify.data.List; import com.example.listify.data.List;
import com.example.listify.data.ListEntry; import com.example.listify.data.ListEntry;
import com.example.listify.model.Product; import com.example.listify.model.Product;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException; import org.json.JSONException;
import java.io.IOException; import java.io.IOException;
@ -239,7 +227,7 @@ public class ItemDetails extends AppCompatActivity implements ListPickerDialogFr
Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); Requestor requestor = new Requestor(am, configs.getProperty("apiKey"));
SynchronousReceiver<Integer> idReceiver = new SynchronousReceiver<>(); SynchronousReceiver<Integer> idReceiver = new SynchronousReceiver<>();
com.example.listify.data.List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); com.example.listify.data.List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli(), -1);
Thread t = new Thread(new Runnable() { Thread t = new Thread(new Runnable() {
@Override @Override

View File

@ -17,6 +17,7 @@ import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI; import androidx.navigation.ui.NavigationUI;
import com.amplifyframework.auth.AuthException; import com.amplifyframework.auth.AuthException;
import com.example.listify.data.List; import com.example.listify.data.List;
import com.example.listify.data.ListReposition;
import com.example.listify.data.SearchHistory; import com.example.listify.data.SearchHistory;
import com.example.listify.ui.LoginPage; import com.example.listify.ui.LoginPage;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
@ -108,6 +109,7 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF
requestor.getObject("N/A", SearchHistory.class, historyReceiver, historyReceiver); requestor.getObject("N/A", SearchHistory.class, historyReceiver, historyReceiver);
try { try {
System.out.println(historyReceiver.await()); System.out.println(historyReceiver.await());
requestor.putObject(new ListReposition(291, 1));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -205,7 +207,7 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF
Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); Requestor requestor = new Requestor(am, configs.getProperty("apiKey"));
SynchronousReceiver<Integer> idReceiver = new SynchronousReceiver<>(); SynchronousReceiver<Integer> idReceiver = new SynchronousReceiver<>();
List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli(), -1);
try { try {
requestor.postObject(newList, idReceiver, idReceiver); requestor.postObject(newList, idReceiver, idReceiver);

View File

@ -9,18 +9,20 @@ public class List {
long lastUpdated; long lastUpdated;
final ListEntry[] entries; final ListEntry[] entries;
boolean shared; boolean shared;
Integer uiPosition;
public List(Integer itemID, String name, String owner, long lastUpdated, ListEntry[] entries, boolean shared) { public List(Integer itemID, String name, String owner, long lastUpdated, ListEntry[] entries, boolean shared, Integer uiPosition) {
this.itemID = itemID; this.itemID = itemID;
this.name = name; this.name = name;
this.owner = owner; this.owner = owner;
this.lastUpdated = lastUpdated; this.lastUpdated = lastUpdated;
this.entries = entries; this.entries = entries;
this.shared = false; this.shared = false;
this.uiPosition = uiPosition;
} }
public List(Integer itemID, String name, String owner, long lastUpdated) { public List(Integer itemID, String name, String owner, long lastUpdated, Integer uiPosition) {
this(itemID, name, owner, lastUpdated, null, false); this(itemID, name, owner, lastUpdated, null, false, uiPosition);
} }
@Override @Override
@ -32,6 +34,7 @@ public class List {
", lastUpdated=" + lastUpdated + ", lastUpdated=" + lastUpdated +
", entries=" + Arrays.toString(entries) + ", entries=" + Arrays.toString(entries) +
", shared=" + shared + ", shared=" + shared +
", uiPosition=" + uiPosition +
'}'; '}';
} }
@ -75,6 +78,13 @@ public class List {
this.shared = shared; this.shared = shared;
} }
public Integer getUiPosition() {
return uiPosition;
}
public void setUiPosition(Integer uiPosition) {
this.uiPosition = uiPosition;
public ListEntry[] getEntries() { public ListEntry[] getEntries() {
return entries; return entries;
} }

View File

@ -0,0 +1,35 @@
package com.example.listify.data;
public class ListReposition {
Integer listID;
Integer newPosition;
public ListReposition(Integer listID, Integer newPosition) {
this.listID = listID;
this.newPosition = newPosition;
}
@Override
public String toString() {
return "ListReposition{" +
"listID=" + listID +
", newPosition=" + newPosition +
'}';
}
public Integer getListID() {
return listID;
}
public void setListID(Integer listID) {
this.listID = listID;
}
public Integer getNewPosition() {
return newPosition;
}
public void setNewPosition(Integer newPosition) {
this.newPosition = newPosition;
}
}

View File

@ -88,7 +88,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O
Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); Requestor requestor = new Requestor(am, configs.getProperty("apiKey"));
SynchronousReceiver<Integer> idReceiver = new SynchronousReceiver<>(); SynchronousReceiver<Integer> idReceiver = new SynchronousReceiver<>();
List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli() , -1);
try { try {
requestor.postObject(newList, idReceiver, idReceiver); requestor.postObject(newList, idReceiver, idReceiver);