refactoring content

This commit is contained in:
yb 2022-07-17 16:17:29 +02:00
parent faf1994962
commit 809ef00a99
52 changed files with 1296 additions and 295 deletions

View File

@ -3,12 +3,34 @@ package eu.csc.log;
import android.content.Context;
import eu.csc.vehown.ApplicationEx;
import eu.csc.vehown.log.ILogger;
import eu.csc.vehown.persist.localstorage.entity.EntityLog;
import eu.csc.vehown.ui.viewmodels.AppViewModelFactory;
public class Log {
private static final String TAG = "VehAppLog";
private static Context ctx;
public static void setup(Context context) {
ctx = context;
//setLevel(context);
//setupBugsnag(context);
}
public static ILogger getLogger(String tag){
return new ILogger() {
@Override
public void d(String msg) {
Log.d(tag, msg);
}
@Override
public void d(String tag, String msg) {
Log.d(tag, msg);
}
};
}
public static void d(String msg) {
d(TAG, msg);
@ -16,16 +38,22 @@ public class Log {
public static void d(String tag, String msg) {
android.util.Log.d(tag, msg);
if(ctx !=null)
{
EntityLog.log(ctx, EntityLog.Type.General, tag+ ": " + msg);
if (ctx != null) {
EntityLog.log(ctx, EntityLog.Type.General, tag + ": " + msg);
}
//EntityLog.log();
}
public static void setup(Context context) {
ctx = context;
//setLevel(context);
//setupBugsnag(context);
public static void d(String tag, String msg, Integer count) {
d(tag, String.join("\n", msg, "----", "ITEMS " + count + "", "----"));
}
public static void d(String tag, String msg, Exception ex) {
d(tag, String.join("\n", msg, "----", ex.toString(), "----"));
}
public static ILogger getLogger(Class<? extends AppViewModelFactory> clazz) {
return getLogger(clazz.getSimpleName());
}
}

View File

@ -8,20 +8,33 @@ import java.util.Date;
import eu.csc.log.Log;
import eu.csc.vehown.persist.localstorage.PersistenceFactory;
import eu.csc.vehown.persist.localstorage.entity.EntityLog;
import eu.csc.vehown.services.rest.vehownserver.VehOwnApiClientFactory;
import lombok.var;
public class ApplicationEx extends Application {@Override
public void onCreate() {
super.onCreate();
android.util.Log.d("ApplicationEx", "item.toString()");
Log.setup(this);
VehOwnApiClientFactory.setUrl(this);
var db = PersistenceFactory.generateDatabase(this);
long from = new Date().getTime() - 24 * 3600 * 1000L;
long from2 = new Date().getTime() * 3600 * 1000L;
Log.d("ApplicationEx", "PERS");
for(var item:db.log().getLogs(from, null)){
Log.d("ApplicationEx", "LOGS");
for(var item:db.log().getLogs(from)){
android.util.Log.d("LOGS", item.toString());
}
Log.d("ApplicationEx", "DELETE OLD LOGS", db.log().countDeleteLogs(from2, 1000));
db.log().deleteLogs(from2, 1000);
}
}

View File

@ -1,6 +1,8 @@
package eu.csc.vehown.services.rest;
import android.content.Context;
import eu.csc.log.Log;
import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
import eu.csc.vehown.services.serialization.JSONHelper;
import okhttp3.Interceptor;
@ -19,6 +21,7 @@ public class RetrofitApiClientFactory {
public static final String AUTHENTICATION_API_URL = "http://127.0.0.1:8755/";
private static final String API_URL = "http://10.10.101.30:8000/repair/";
private static final String TAG = RetrofitApiClientFactory.class.getSimpleName();
public static LeaseApiClient getLeaseClient(String url) {
@ -36,7 +39,7 @@ public class RetrofitApiClientFactory {
public static RetrofitApiClient getClient(Context context) {
String token = SharedPreferencesFactory.getInstance(context).getApiToken();
String token = SharedPreferencesFactory.getInstance(context, Log.getLogger(TAG)).getApiToken();
return getClient(API_URL, token);
}

View File

@ -1,6 +1,7 @@
package eu.csc.vehown.services.rest.vehownserver;
import eu.csc.ODPAppVehOwnServer.models.VehicleBrandDto;
import eu.csc.ODPAppVehOwnServer.models.data.DeviceArticleDto;
import eu.csc.ODPAppVehOwnServer.models.data.LanguageDto;
import eu.csc.ODPAppVehOwnServer.models.data.PropulsionTypeDto;
import eu.csc.ODPAppVehOwnServer.models.regist.CustomerDeviceDto;
@ -29,4 +30,6 @@ public interface IVehOwnAppClient {
Call<CustomerDeviceDto> registerCustomerDevice(String serialnumber);
Call<DeviceArticleDto> findDeviceArticleInfo(String serialnumber);
}

View File

@ -3,6 +3,7 @@ package eu.csc.vehown.services.rest.vehownserver;
import eu.csc.ODPAppVehOwnServer.client.service.ClientService;
import eu.csc.ODPAppVehOwnServer.client.service.CustomerService;
import eu.csc.ODPAppVehOwnServer.models.VehicleBrandDto;
import eu.csc.ODPAppVehOwnServer.models.data.DeviceArticleDto;
import eu.csc.ODPAppVehOwnServer.models.data.LanguageDto;
import eu.csc.ODPAppVehOwnServer.models.data.PropulsionTypeDto;
import eu.csc.ODPAppVehOwnServer.models.regist.CustomerDeviceDto;
@ -85,4 +86,9 @@ public class ServerVehicleApiClient implements IVehOwnAppClient {
public Call<CustomerDeviceDto> registerCustomerDevice(String serialnumber) {
return customerService.registerCustomerDevices(serialnumber);
}
@Override
public Call<DeviceArticleDto> findDeviceArticleInfo(String serialnumber) {
throw new UnsupportedOperationException();
}
}

View File

@ -2,11 +2,14 @@ package eu.csc.vehown.services.rest.vehownserver;
import eu.csc.ODPAppVehOwnServer.models.VehicleBrandDto;
import eu.csc.ODPAppVehOwnServer.models.VehicleModelDto;
import eu.csc.ODPAppVehOwnServer.models.data.DeviceArticleDto;
import eu.csc.ODPAppVehOwnServer.models.data.DeviceDto;
import eu.csc.ODPAppVehOwnServer.models.data.LanguageDto;
import eu.csc.ODPAppVehOwnServer.models.data.PropulsionTypeDto;
import eu.csc.ODPAppVehOwnServer.models.regist.CustomerDeviceDto;
import eu.csc.ODPAppVehOwnServer.models.regist.CustomerVehicleDto;
import eu.csc.vehown.data.model.Customer;
import eu.csc.vehown.data.model.CustomerVehicle;
import eu.csc.vehown.data.model.LoggedInUser;
import eu.csc.vehown.data.model.Vehicle;
import eu.csc.vehown.services.rest.vehownserver.pub.OfflineDummyCall;
@ -24,6 +27,10 @@ public class VehOwnAppClientDummy implements IVehOwnAppClient {
private final List<VehicleModelDto> vehicleModelDtos;
private final List<PropulsionTypeDto> propulsionTypeDtos;
private final List<CustomerVehicleDto> customerVehicles;
private final List<DeviceArticleDto> deviceArticleDtos;
@Getter
private final LoggedInUser loggedInUser;
@ -68,6 +75,26 @@ public class VehOwnAppClientDummy implements IVehOwnAppClient {
loggedInUser.setLogin("test@test.test");
loggedInUser.setLanguage("en");
var customerVehicleA = new CustomerVehicleDto();
customerVehicleA.setBrandId("ford");
customerVehicleA.setModelId("focus");
customerVehicleA.setVin("12345");
customerVehicleA.setLicensePlate("HS-ABC");
customerVehicleA.setPropulsionType("gasoline");
customerVehicles = new ArrayList<>();
customerVehicles.add(customerVehicleA);
DeviceDto deviceA = new DeviceDto();
deviceA.setName("DEVICE_A");
deviceA.setDeviceNumber("RANDOM_NUMBER");
DeviceArticleDto deviceArticleDtoA = new DeviceArticleDto();
deviceArticleDtoA.setSerialnumber("s");
deviceArticleDtoA.setDevice(deviceA);
deviceArticleDtos = new ArrayList<>();
deviceArticleDtos.add(deviceArticleDtoA);
}
@Override
@ -119,6 +146,8 @@ public class VehOwnAppClientDummy implements IVehOwnAppClient {
dto.setModelId(body.getModel());
dto.setLicensePlate(body.getLicensePlate());
dto.setVin(body.getVin());
dto.setPropulsionType(body.getPropulsionType());
//ToDo dto.setR(body.getRegistrationDate());
return OfflineDummyCall.getInstance(dto);
}
@ -130,7 +159,7 @@ public class VehOwnAppClientDummy implements IVehOwnAppClient {
@Override
public Call<List<CustomerVehicleDto>> getCustomerVehicles() throws IOException {
return OfflineDummyCall.getInstance(new ArrayList<>());
return OfflineDummyCall.getInstance(customerVehicles);
}
@Override
@ -146,6 +175,19 @@ public class VehOwnAppClientDummy implements IVehOwnAppClient {
return OfflineDummyCall.getInstance(body2);
}
@Override
public Call<DeviceArticleDto> findDeviceArticleInfo(String serialnumber) {
var opDevice = deviceArticleDtos
.stream().filter(x->x.getSerialnumber().equals(serialnumber)).findFirst();
if(opDevice.isPresent())
{
return new OfflineDummyCall<DeviceArticleDto>(opDevice.get());
}
//ToDo better
return new OfflineDummyCall<>(null);
}
//endregion

View File

@ -22,6 +22,11 @@ public final class OfflineDummyCall<T> implements Call<T> {
@Override
public Response<T> execute() {
try{
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Response.success(this.content);
}

View File

@ -1,9 +1,42 @@
package eu.csc.vehown.ui.base;
import android.content.Context;
import android.content.DialogInterface;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import eu.csc.vehown.ui.pub.UIUtils;
public abstract class AbstractFragment extends Fragment {
public static final String CUSTOM_RESULT_CODE = "c_c";
protected void showToast(Context context, String text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
protected void showToast(String text) {
Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
}
protected void showConfirmationDialog(DialogInterface.OnClickListener ok, DialogInterface.OnClickListener obort) {
UIUtils.showConfirmationDialog(getContext(), "Are you sure", "Are you Sure", ok, obort).show();
}
protected void showConfirmationDialog(DialogInterface.OnClickListener ok) {
UIUtils.showConfirmationDialog(getContext(), "Are you sure", "Are you Sure", ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).show();
}
}

View File

@ -7,6 +7,7 @@ import android.os.Bundle;
import android.util.Log;
import eu.csc.vehown.R;
import eu.csc.vehown.ui.fragments.UserProfileFragment;
import eu.csc.vehown.ui.fragments.details.FragmentDetailDevice;
import eu.csc.vehown.ui.registration.device.DeviceRegistrationFragment;
import eu.csc.vehown.ui.registration.vehicle.VehicleRegistrationFragment;
@ -20,6 +21,7 @@ public class ActivityBaseDetailContent extends AbstractAppCompatActivity {
private static final String ARG_ITEM_TYPE = "ty";
private static final int ARG_ITEM_TYPE_VEHICLE = 1;
private static final int ARG_ITEM_TYPE_DEVICE = 2;
private static final int ARG_ITEM_TYPE_PROFILE = 10;
private static final int ARG_ITEM_TYPE_VEHICLE_REGISTER = 3;
private static final int ARG_ITEM_TYPE_DEVICE_REGISTER = 4;
@ -37,6 +39,12 @@ public class ActivityBaseDetailContent extends AbstractAppCompatActivity {
return intent;
}
public static Intent getProfileInstance(FragmentActivity activity) {
Intent intent = new Intent(activity, ActivityBaseDetailContent.class);
intent.putExtra(ARG_ITEM_TYPE, ARG_ITEM_TYPE_PROFILE);
return intent;
}
public static Intent getDeviceRegistrationInstance(FragmentActivity activity, int resultCode) {
Intent intent = new Intent(activity, ActivityBaseDetailContent.class);
intent.putExtra(ARG_ITEM_TYPE, ARG_ITEM_TYPE_DEVICE_REGISTER);
@ -78,6 +86,9 @@ public class ActivityBaseDetailContent extends AbstractAppCompatActivity {
case ARG_ITEM_TYPE_DEVICE:
switchFragment(R.id.flContent, FragmentDetailDevice.newInstance(id));
break;
case ARG_ITEM_TYPE_PROFILE:
switchFragment(R.id.flContent, UserProfileFragment.newInstance());
break;
}
} else {

View File

@ -0,0 +1,131 @@
package eu.csc.vehown.ui.fragments;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.List;
import eu.csc.vehown.Helper;
import eu.csc.vehown.R;
import eu.csc.vehown.data.model.Vehicle;
import eu.csc.vehown.databinding.UserProfileFragmentBinding;
import eu.csc.vehown.ui.base.AbstractFragment;
import eu.csc.vehown.ui.base.ActivityBaseDetailContent;
import eu.csc.vehown.ui.base.BaseRegistrationActivity;
import eu.csc.vehown.ui.fragments.ui.login.LoginViewModel;
import eu.csc.vehown.ui.pub.UIUtils;
import eu.csc.vehown.ui.viewmodels.AppViewModelFactory;
import lombok.var;
/**
* @see eu.csc.vehown.ui.login.LoginActivity
*/
public class UserProfileFragment extends AbstractFragment {
private UserProfileViewModel mViewModel;
private UserProfileFragmentBinding binding;
public static UserProfileFragment newInstance() {
return new UserProfileFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = UserProfileFragmentBinding.inflate(getLayoutInflater());
return binding.getRoot();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = new ViewModelProvider(this, new AppViewModelFactory(getContext()))
.get(UserProfileViewModel.class);
mViewModel.getMutableLiveDataSuccess().observe(getViewLifecycleOwner(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if (aBoolean) {
getView().setEnabled(aBoolean);
}
mViewModel.refreshContent();
}
});
mViewModel.getMVehicles().observe(getViewLifecycleOwner(), new Observer<List<Vehicle>>() {
@Override
public void onChanged(List<Vehicle> vehicles) {
binding.tvVehicleCount.setText(String.format(Helper.getString(getContext(), R.string.text_vehicles_count), vehicles.size()));
}
});
binding.btnVehicleAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
var intent = ActivityBaseDetailContent.getVehicleRegistrationInstance(getActivity(), 1);
getActivity().startActivityForResult(intent, 1);
}
});
binding.btnVehicleDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mViewModel.deleteVehicles();
}
});
mViewModel.getMRefreshVehicles().observe(getViewLifecycleOwner(), new Observer<List<Vehicle>>() {
@Override
public void onChanged(List<Vehicle> vehicles) {
var dialog = UIUtils.showConfirmationDialog(getContext(), "Result", "Found: " + vehicles.size(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
showToast(getContext(), "SAVE");
mViewModel.storeRemoteVehicles(vehicles);
mViewModel.refreshContent();
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
showToast(getContext(), "Abort");
}
});
dialog.show();
}
});
binding.btnVehicleRefresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setUiStatus(false);
mViewModel.refreshVehicles();
}
});
mViewModel.refreshContent();
// TODO: Use the ViewModel
}
private void setUiStatus(boolean b) {
getView().setEnabled(b);
}
}

View File

@ -0,0 +1,80 @@
package eu.csc.vehown.ui.fragments;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import eu.csc.log.Log;
import eu.csc.vehown.data.model.CustomerDevice;
import eu.csc.vehown.ui.registration.data.CustomerContentRepository;
import eu.csc.vehown.ui.registration.data.CustomerVehicleRegistrationRepository;
import java.util.List;
import eu.csc.vehown.data.model.Vehicle;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.ui.models.Result;
import eu.csc.vehown.ui.viewmodels.AbstractBaseViewModel;
import lombok.Getter;
import lombok.var;
public class UserProfileViewModel extends AbstractBaseViewModel {
private static final String TAG = UserProfileViewModel.class.getSimpleName();
private final CustomerContentRepository repository;
@Getter
private final MutableLiveData<Boolean> mutableLiveDataSuccess;
@Getter
private final MutableLiveData<List<Vehicle>> mVehicles;
@Getter
private final MutableLiveData<List<CustomerDevice>> mStoredDevices;
@Getter
private final MutableLiveData<List<Vehicle>> mRefreshVehicles;
public UserProfileViewModel(LocalStorageClient localStorage, CustomerContentRepository repository) {
super(localStorage);
this.repository = repository;
mutableLiveDataSuccess = new MutableLiveData<>();
mVehicles = new MutableLiveData<>();
mRefreshVehicles = new MutableLiveData<>();
mStoredDevices = new MutableLiveData<>();
}
public void refreshVehicles() {
d(TAG, "refreshVehicles");
executorService.execute(new Runnable() {
@Override
public void run() {
var result = repository.fetchCustomerVehiclesRemote();
d(TAG, result.toString());
if(result instanceof Result.Success){
mutableLiveDataSuccess.postValue(true);
mRefreshVehicles.postValue(result.getSuccessBody());
}else
mutableLiveDataSuccess.postValue(false);
}
});
}
public void deleteVehicles() {
repository.deleteCustomerVehicles();
mutableLiveDataSuccess.postValue(true);
}
public void refreshContent(){
mVehicles.postValue(repository.getStoredUserVehicles());
mStoredDevices.postValue(repository.getStoredUserDevices());
}
public void storeRemoteVehicles(List<Vehicle> items) {
repository.storeRemoteCustomerVehicles(items);
}
}

View File

@ -41,6 +41,7 @@ public class LoginRepository {
public void logout() {
user = null;
localStorage.doLogout();
dataSource.logout();
}
@ -48,8 +49,6 @@ public class LoginRepository {
this.user = user;
localStorage.setLoggedInUser(user);
localStorage.storeCustomer(user);
localStorage.setIsLoggedIn(true);
// If user credentials will be cached in local storage, it is recommended it be encrypted
// @see https://developer.android.com/training/articles/keystore
}

View File

@ -7,6 +7,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@ -27,13 +29,16 @@ import eu.csc.vehown.R;
import eu.csc.vehown.databinding.FragmentLoginBinding;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
import eu.csc.vehown.ui.base.AbstractFragment;
import eu.csc.vehown.ui.login.LoginActivity;
import eu.csc.vehown.ui.models.LoggedInUserView;
import eu.csc.vehown.ui.models.LoginFormState;
import eu.csc.vehown.ui.models.LoginResult;
import eu.csc.vehown.ui.registration.customer.FragmentCustomerRegistrationViewModel;
import eu.csc.vehown.ui.viewmodels.AppViewModelFactory;
import lombok.var;
public class LoginFragment extends Fragment {
public class LoginFragment extends AbstractFragment {
private static final String TAG = LoginFragment.class.getSimpleName();
private LoginViewModel loginViewModel;
@ -49,7 +54,7 @@ public class LoginFragment extends Fragment {
binding = FragmentLoginBinding.inflate(inflater, container, false);
localStorageClient = SharedPreferencesFactory.getInstance(getContext());
localStorageClient = SharedPreferencesFactory.getInstance(getContext(), Log.getLogger(TAG));
return binding.getRoot();
@ -69,6 +74,8 @@ public class LoginFragment extends Fragment {
final CheckBox cbRemember = binding.cbRemember;
final ProgressBar loadingProgressBar = binding.pbLoading;
initUi();
loginViewModel.getLoginFormState().observe(getViewLifecycleOwner(), new Observer<LoginFormState>() {
@Override
public void onChanged(@Nullable LoginFormState loginFormState) {
@ -144,7 +151,7 @@ public class LoginFragment extends Fragment {
if (localStorageClient.getIsLoggedIn() && localStorageClient.getLoggedInUser() != null && localStorageClient.getLoggedInUser().getPassword() != null) {
eu.csc.log.Log.d(TAG, "IS LOGGED IN");
binding.btnLogout.setEnabled(true);
//binding.btnLogout.setEnabled(true);
usernameEditText.setText(localStorageClient.getLoggedInUser().getEmail());
passwordEditText.setText(localStorageClient.getLoggedInUser().getPassword());
} else {
@ -153,6 +160,30 @@ public class LoginFragment extends Fragment {
usernameEditText.setText("test@test.test");
passwordEditText.setText("yannyann1");
}
binding.btnLogout.setEnabled(true); logoutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showConfirmationDialog(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
loginViewModel.handleLogout();
var intent = new Intent(getActivity(), LoginActivity.class);
showToast("Success");
startActivity(intent);
// getActivity().finish();
}
});
}
});
}
private void initUi() {
// binding.btnLogout.setVisibility(localStorageClient.getIsLoggedIn() ? View.VISIBLE:View.INVISIBLE);
// binding.btnLogin.setVisibility(!localStorageClient.getIsLoggedIn() ? View.VISIBLE:View.INVISIBLE);
binding.btnLogin.setEnabled(!localStorageClient.getIsLoggedIn());
binding.btnLogout.setEnabled(localStorageClient.getIsLoggedIn());
}
private void updateUiWithUser(LoggedInUserView model) {

View File

@ -69,5 +69,7 @@ public class LoginViewModel extends AbstractBaseViewModel {
}
public void handleLogout() {
loginRepository.logout();
}
}

View File

@ -1,76 +1,122 @@
package eu.csc.vehown.ui.login;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.fragment.app.FragmentTransaction;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import eu.csc.vehown.R;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
import eu.csc.vehown.ui.base.AbstractAppCompatActivity;
import eu.csc.vehown.ui.base.ActivityBaseDetailContent;
import eu.csc.vehown.ui.fragments.UserProfileFragment;
import eu.csc.vehown.ui.fragments.ui.login.LoginFragment;
import eu.csc.vehown.ui.registration.customer.FragmentCustomerRegistration;
/**
* @see FragmentCustomerRegistration
* @see LoginFragment
* @see UserProfileFragment
*/
public class LoginActivity extends AppCompatActivity {
public class LoginActivity
extends AbstractAppCompatActivity
implements BottomNavigationView.OnNavigationItemSelectedListener {
private Button btnSwitchView;
private BottomNavigationView navView;
private LocalStorageClient sharedPref;
private NavController navController;
public static Intent getInstance(Activity activity) {
private boolean loginVisible;
Intent intent = new Intent(activity, ActivityBaseDetailContent.class);
return intent;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
navView = findViewById(R.id.nav_view);
sharedPref = SharedPreferencesFactory.getInstance(getApplicationContext());
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_customer_register_login,
R.id.navigation_customer_register_register,
R.id.navigation_customer_register_profile)
.build();
navController = Navigation.findNavController(this, R.id.content_frame);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
navView.setOnNavigationItemSelectedListener(this);
showPages();
ActionBar actionBar = getSupportActionBar();
// showing the back button in action bar
actionBar.setDisplayHomeAsUpEnabled(true);
btnSwitchView = findViewById(R.id.btnSwitchView);
btnSwitchView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
switchView();
}
private void showPages() {
/*
navView.getMenu().findItem(R.id.navigation_customer_register_login)
.setVisible(!sharedPref.getIsLoggedIn());
navView.getMenu().findItem(R.id.navigation_customer_register_register)
.setVisible(!sharedPref.getIsLoggedIn());
navView.getMenu().findItem(R.id.navigation_customer_register_profile)
.setVisible(sharedPref.getIsLoggedIn());
if(SharedPreferencesFactory.isLoggedIn(getApplicationContext())){
navController.navigate(R.id.navigation_customer_register_profile);
}else{
navController.navigate(R.id.navigation_customer_register_login);
}
*/
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.navigation_customer_register_login:{
switchFragment(R.id.content_frame, new LoginFragment());
break;
}
});
case R.id.navigation_customer_register_register:{
switchFragment(R.id.content_frame, new FragmentCustomerRegistration());
break;
}
case R.id.navigation_customer_register_profile:{
switchFragment(R.id.content_frame, new UserProfileFragment());
break;
}
}
showLogin();
}
private void switchView() {
if (loginVisible) {
showRegistration();
} else
showLogin();
}
private void showRegistration() {
FragmentCustomerRegistration fragment = new FragmentCustomerRegistration();
fragment.setArguments(new Bundle());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.commit();
loginVisible = false;
btnSwitchView.setText("Login");
}
private void showLogin() {
LoginFragment fragment = new LoginFragment();
fragment.setArguments(new Bundle());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.commit();
loginVisible = true;
btnSwitchView.setText("Register");
return true;
}
}

View File

@ -27,8 +27,10 @@ import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
import eu.csc.vehown.services.notifications.NotificationService;
import eu.csc.vehown.services.rest.vehownserver.VehOwnApiClientFactory;
import eu.csc.vehown.ugp.WifiConnectedReceiver;
import eu.csc.vehown.ui.base.ActivityBaseDetailContent;
import eu.csc.vehown.ui.base.BaseRegistrationActivity;
import eu.csc.vehown.ui.content.ActivityLocalContentNavigation;
import eu.csc.vehown.ui.fragments.UserProfileFragment;
import eu.csc.vehown.ui.login.LoginActivity;
import eu.csc.vehown.ui.main.dboard.DashboardFragment;
import eu.csc.vehown.ui.md.ItemDetailHostActivity;
@ -97,6 +99,8 @@ public class MainActivity extends AppCompatActivity {
}
//startActivity(ActivityBaseDetailContent.getProfileInstance(this));
showProfile();
}
private void setup() {
@ -188,6 +192,13 @@ public class MainActivity extends AppCompatActivity {
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.commit();
}
private void showProfile() {
UserProfileFragment fragment = new UserProfileFragment();
fragment.setArguments(new Bundle());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.commit();
}
private Intent showLogin() {
return new Intent(this, LoginActivity.class);

View File

@ -10,6 +10,8 @@ import android.widget.TextView;
import androidx.fragment.app.Fragment;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import eu.csc.log.Log;
import eu.csc.vehown.R;
import eu.csc.vehown.databinding.FragmentItemDetailBinding;
import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
@ -30,6 +32,7 @@ public class ItemDetailFragment extends Fragment {
* represents.
*/
public static final String ARG_ITEM_ID = "item_id";
private static final String TAG = ItemDetailFragment.class.getSimpleName();
/**
* The placeholder content this fragment is presenting.
@ -64,7 +67,7 @@ public class ItemDetailFragment extends Fragment {
// arguments. In a real-world scenario, use a Loader
// to load content from a content provider.
String id = getArguments().getString(ARG_ITEM_ID);
var oV =SharedPreferencesFactory.getInstance(this.getContext()).findVehicleByVin(id);
var oV =SharedPreferencesFactory.getInstance(this.getContext(), Log.getLogger(TAG)).findVehicleByVin(id);
if(oV.isPresent()){
mItem = new PlaceholderContent.PlaceholderItem(oV.get().getVin(), oV.get().toString(), oV.get().toString()) ;

View File

@ -45,6 +45,7 @@ import static eu.csc.vehown.ui.md.ItemDetailHostActivity.TYPE_ID_VEHICLE;
*/
public class ItemListFragment extends Fragment {
private static final String TAG = ItemListFragment.class.getSimpleName();
/**
* Method to intercept global key events in the
* item list fragment to trigger keyboard shortcuts
@ -186,7 +187,7 @@ public class ItemListFragment extends Fragment {
break;
}
for (var vehicle : SharedPreferencesFactory.getInstance(getContext()).loadVehicles()
for (var vehicle : SharedPreferencesFactory.getInstance(getContext(), eu.csc.log.Log.getLogger(TAG)).loadVehicles()
) {
items.add(new PlaceholderContent.PlaceholderItem(vehicle.getVin(), vehicle.getModel(), vehicle.toString()));
}

View File

@ -8,6 +8,18 @@ public class Result<T> {
private Result() {
}
public boolean isSuccess(){
return this instanceof Result.Success;
}
public T getSuccessBody(){
if(isSuccess())
return ((Success<T>)this).data;
return null;
}
@Override
public String toString() {
if (this instanceof Result.Success) {

View File

@ -5,6 +5,8 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.DatePicker;
import androidx.constraintlayout.widget.ConstraintLayout;
@ -12,6 +14,8 @@ import androidx.fragment.app.FragmentActivity;
import java.util.Date;
import eu.csc.vehown.R;
public class UIUtils {
@ -36,19 +40,15 @@ public class UIUtils {
}
});
builder.setNegativeButton("Abort", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
dialog.dismiss();
}
});
// 3. Get the <code><a href="/reference/android/app/AlertDialog.html">AlertDialog</a></code> from <code><a href="/reference/android/app/AlertDialog.Builder.html#create()">create()</a></code>
AlertDialog dialog = builder.create();
dialog.show();
}
public static AlertDialog showConfirmationDialog(Context context, DialogInterface.OnClickListener ok, DialogInterface.OnClickListener abort) {
public static AlertDialog showConfirmationDialog(Context context,
DialogInterface.OnClickListener ok
, DialogInterface.OnClickListener abort) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// 2. Chain together various setter methods to set the dialog characteristics
@ -56,10 +56,48 @@ public class UIUtils {
.setTitle("Confirm");
builder.setPositiveButton("Ok", ok);
builder.setNegativeButton("Abort",abort);
builder.setNegativeButton("Abort", abort);
// 3. Get the <code><a href="/reference/android/app/AlertDialog.html">AlertDialog</a></code> from <code><a href="/reference/android/app/AlertDialog.Builder.html#create()">create()</a></code>
AlertDialog dialog = builder.create();
return dialog;
return dialog;
}
public static AlertDialog showConfirmationDialog(Context context,
String title, String msg,
DialogInterface.OnClickListener ok) {
return showConfirmationDialog(context, title, msg, ok, null);
}
public static AlertDialog showConfirmationDialog(Context context,
String title, String msg,
DialogInterface.OnClickListener ok, DialogInterface.OnClickListener abort) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage(msg)
.setTitle(title);
builder.setPositiveButton("Ok", ok);
if (abort != null)
builder.setNegativeButton("Abort", abort);
// 3. Get the <code><a href="/reference/android/app/AlertDialog.html">AlertDialog</a></code> from <code><a href="/reference/android/app/AlertDialog.Builder.html#create()">create()</a></code>
AlertDialog dialog = builder.create();
return dialog;
}
//region BITMAPS
public static Bitmap loadBitmap(Context context, int bitmapId) {
return BitmapFactory.decodeResource(context.getResources(), bitmapId);
}
public static Bitmap getBitmapNoVehicleImage(Context context) {
return loadBitmap(context, R.drawable.ic_default_vehicle);
}
//endregion
}

View File

@ -51,7 +51,7 @@ public class RegisterCustomerActivity
model = new ViewModelProvider(this, new AppViewModelFactory(this))
.get(RegistrationViewModel.class);
sharedPref = SharedPreferencesFactory.getInstance(getApplicationContext());
sharedPref = SharedPreferencesFactory.getInstance(getApplicationContext(), eu.csc.log.Log.getLogger(TAG));
binding = ActivityRegisterCustomerBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());

View File

@ -173,46 +173,15 @@ public class RegisterVehicleActivity extends AppCompatActivity implements IVehOw
});
binding.btnRegisterVehicle.setOnClickListener(v -> {
Vehicle vehicle = getVehicle();
viewModel
.getRepository()
.storeCustomerVehicle(vehicle);
//ToDo implement
viewModel.storeVehicle(getVehicle());
//ToDo run RestCall
/*
try {
var oCustomer = sharedPref.loadCustomer();
ö
if(!oCustomer.isPresent())
{
//ToDo handle Customer isNot Set
return;
}
VehOwnApiClientFactory.getAuthenticatedDataClient(oCustomer.get())
.registerCustomerVehicle(vehicle)
.enqueue(new Callback<CustomerVehicleDto>() {
@Override
public void onResponse(Call<CustomerVehicleDto> call, Response<CustomerVehicleDto> response) {
}
@Override
public void onFailure(Call<CustomerVehicleDto> call, Throwable t) {
}
});
} catch (IOException e) {
e.printStackTrace();
}
*/
});
binding.btnUnregisterVehicle.setOnClickListener(v -> {
viewModel.unregisterVehicle(getVehicle().getStoredVin());
//TODO? viewModel.unregisterVehicle();
});

View File

@ -1,14 +1,21 @@
package eu.csc.vehown.ui.registration;
import android.content.Context;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import eu.csc.vehown.data.model.*;
import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
import eu.csc.vehown.services.rest.vehownserver.VehOwnApiClientFactory;
import eu.csc.vehown.ui.modal.Helper;
import eu.csc.vehown.ui.models.RegisteredVehicle;
import eu.csc.vehown.ui.models.Result;
import eu.csc.vehown.ui.registration.data.CustomerVehicleRegistrationRepository;
import eu.csc.vehown.ui.viewmodels.AbstractBaseViewModel;
import lombok.Getter;
import lombok.var;
import java.io.IOException;
import java.util.ArrayList;
@ -16,13 +23,10 @@ import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RegistrationViewModel extends ViewModel {
public class RegistrationViewModel extends AbstractBaseViewModel {
@Getter
private final CustomerVehicleRegistrationRepository repository;
private final Context context;
ExecutorService executorService = Executors.newFixedThreadPool(4);
private final MutableLiveData<List<Language>> languages;
@ -38,9 +42,11 @@ public class RegistrationViewModel extends ViewModel {
@Getter
private final MutableLiveData<Vehicle> currentVehicle;
private final MutableLiveData<Result<RegisteredVehicle>> mRegisteredVehicleResult;
public RegistrationViewModel(CustomerVehicleRegistrationRepository repository, Context context) {
super(context);
languages = new MutableLiveData<>();
vehicleBrands = new MutableLiveData<>();
vehiclePropulsionTypes = new MutableLiveData<>();
@ -48,10 +54,10 @@ public class RegistrationViewModel extends ViewModel {
logginResult = new MutableLiveData<>();
this.context = context;
this.repository = repository;
currentVehicle = new MutableLiveData<>();
mRegisteredVehicleResult = new MutableLiveData<>();
}
public List<Language> getLanguages() {
@ -143,8 +149,19 @@ public class RegistrationViewModel extends ViewModel {
public void storeVehicle(Vehicle vehicle) {
Helper.infoToast(context, "Storing vehicle");
getRepository().storeCustomerVehicle(vehicle);
Helper.infoToast(context, "success");
try {
getRepository().storeCustomerVehicle(vehicle);
Helper.infoToast(context, "success");
} catch (Exception e) {
e.printStackTrace();
Helper.showErrorDialog(context, "ERROR", e.toString(), new Helper.IDialogOkHandler() {
@Override
public void onOk() {
}
});
}
}
public void deleteVehicle(Vehicle vehicle) {
@ -157,4 +174,25 @@ public class RegistrationViewModel extends ViewModel {
public void deleteVehicles() {
getRepository().deleteCustomerVehicles();
}
public void registerCustomerVehicle(Vehicle vehicle) {
executorService.execute(new Runnable() {
@Override
public void run() {
var result = getRepository()
.registerCustomerVehicle(vehicle);
mRegisteredVehicleResult.postValue(result);
}
});
}
public LiveData<Result<RegisteredVehicle>> getMRegisteredVehicleResult() {
return this.mRegisteredVehicleResult;
}
public void unregisterVehicle(String vin) {
//ToDo implement
}
}

View File

@ -15,19 +15,19 @@ import eu.csc.vehown.ui.models.LoginFormState;
import eu.csc.vehown.ui.models.LoginResult;
import eu.csc.vehown.ui.models.Result;
import eu.csc.vehown.ui.registration.data.CustomerContentDataSource;
import eu.csc.vehown.ui.registration.data.CustomerRegistrationRepository;
import eu.csc.vehown.ui.registration.data.CustomerContentRepository;
import eu.csc.vehown.ui.viewmodels.AbstractBaseViewModel;
import lombok.Getter;
public class FragmentCustomerRegistrationViewModel extends AbstractBaseViewModel {
private final CustomerContentDataSource customerContentDataSource;
private final CustomerRegistrationRepository repository;
private final CustomerContentRepository repository;
public FragmentCustomerRegistrationViewModel(LocalStorageClient localStorage, Context context, CustomerContentDataSource customerContentDataSource) {
super(localStorage);
this.customerContentDataSource = customerContentDataSource;
this.repository = CustomerRegistrationRepository.getInstance(customerContentDataSource, localStorage);
this.repository = CustomerContentRepository.getInstance(customerContentDataSource, localStorage);
last_customer = localStorage.loadCustomer().orElse(null);
}

View File

@ -2,6 +2,7 @@ package eu.csc.vehown.ui.registration.data;
import androidx.annotation.NonNull;
import eu.csc.ODPAppVehOwnServer.models.data.DeviceArticleDto;
import eu.csc.ODPAppVehOwnServer.models.regist.CustomerVehicleDto;
import eu.csc.vehown.data.model.CustomerDevice;
import eu.csc.vehown.data.model.CustomerVehicle;
@ -22,6 +23,8 @@ import java.util.List;
*/
public class CustomerContentDataSource {
private static final String TAG = CustomerContentDataSource.class.getSimpleName();
public Result<RegisteredVehicle> registerVehicle(@NonNull ICustomer customer, Vehicle vehicle) {
try {
@ -38,7 +41,6 @@ public class CustomerContentDataSource {
result.setPropulsionType(call.body().getPropulsionType());
result.setLicensePlate(call.body().getLicensePlate());
return new Result.Success<>(result);
} else {
return new Result.Error(new Exception(call.toString()));
@ -57,9 +59,8 @@ public class CustomerContentDataSource {
try {
var profile = VehOwnApiClientFactory.fetchUserProfil(email, password);
LoggedInUser fakeUser =
new LoggedInUser(
profile.getEmail(),
profile.getEmail());
new LoggedInUser(profile.getServerId(),
profile);
fakeUser.setStreet(profile.getStreet());
fakeUser.setFirstname(profile.getFirstname());
@ -74,7 +75,7 @@ public class CustomerContentDataSource {
ioException.printStackTrace();
return new Result.Error(new Exception("Error logging in ", ioException));
}catch (Exception ex){
} catch (Exception ex) {
ex.printStackTrace();
return new Result.Error(new Exception("Error logging in ", ex));
@ -90,11 +91,11 @@ public class CustomerContentDataSource {
.execute();
if (result.isSuccessful()) {
LoggedInUser fakeUser =
LoggedInUser loggedInUser =
new LoggedInUser(
result.body().toString(),
customer.getEmail());
return new Result.Success<>(fakeUser);
result.body(),
customer);
return new Result.Success<>(loggedInUser);
} else {
return new Result.Error(new Exception("Error logging in " + result.errorBody().toString()));
}
@ -111,9 +112,9 @@ public class CustomerContentDataSource {
// TODO: revoke authentication
}
public Result<List<CustomerVehicle>> fetchCustomerVehicles(@NonNull ICustomer customer) {
public Result<List<Vehicle>> fetchCustomerVehicles(@NonNull ICustomer customer) {
var result = new ArrayList<CustomerVehicle>();
var result = new ArrayList<Vehicle>();
try {
@ -124,12 +125,13 @@ public class CustomerContentDataSource {
if (remoteContent.isSuccessful() && remoteContent.body() != null) {
for (var remoteItem : remoteContent.body()) {
var item = new CustomerVehicle();
var item = new Vehicle();
item.setBrand(remoteItem.getBrandId());
item.setModel(remoteItem.getModelId());
item.setLicenseplate(remoteItem.getLicensePlate());
item.setLicenseplate(remoteItem.getPropulsionType());
item.setLicensePlate(remoteItem.getLicensePlate());
item.setPropulsionType(remoteItem.getPropulsionType());
item.setVin(remoteItem.getVin());
result.add(item);
}
@ -173,4 +175,23 @@ public class CustomerContentDataSource {
return new Result.Success<>(result);
}
public Result<DeviceArticleDto> fetchCustomerDevice(@NonNull ICustomer customer, @NonNull String serialnumber) {
try {
var service = VehOwnApiClientFactory.getAuthenticatedDataClient(customer)
.findDeviceArticleInfo(serialnumber).execute();
if (service.isSuccessful()) {
return new Result.Success<>(service.body());
} else {
return new Result.Error(new Exception("NOTHING FOUND"));
}
} catch (IOException e) {
e.printStackTrace();
return new Result.Error(e);
}
}
}

View File

@ -3,6 +3,7 @@ package eu.csc.vehown.ui.registration.data;
import java.util.List;
import eu.csc.ODPAppVehOwnServer.client.service.AuthenticationService;
import eu.csc.log.Log;
import eu.csc.vehown.data.model.CustomerDevice;
import eu.csc.vehown.data.model.ICustomer;
import eu.csc.vehown.data.model.LoggedInUser;
@ -17,9 +18,11 @@ import lombok.var;
* Class that requests authentication and user information from the remote data source and
* maintains an in-memory cache of login status and user credentials information.
*/
public class CustomerRegistrationRepository {
public class CustomerContentRepository {
private static volatile CustomerRegistrationRepository instance;
private static final String TAG = CustomerContentRepository.class.getSimpleName();
private static volatile CustomerContentRepository instance;
private CustomerContentDataSource dataSource;
private LocalStorageClient localStorageClient;
@ -30,15 +33,16 @@ public class CustomerRegistrationRepository {
private LoggedInUser user = null;
// private constructor : singleton access
private CustomerRegistrationRepository(CustomerContentDataSource dataSource, LocalStorageClient localStorageClient) {
private CustomerContentRepository(CustomerContentDataSource dataSource, LocalStorageClient localStorageClient) {
this.dataSource = dataSource;
this.localStorageClient = localStorageClient;
this.authenticationService = VehOwnApiClientFactory.getAuthenticationService();
this.user = localStorageClient.getLoggedInUser();
}
public static CustomerRegistrationRepository getInstance(CustomerContentDataSource dataSource, LocalStorageClient localStorageClient) {
public static CustomerContentRepository getInstance(CustomerContentDataSource dataSource, LocalStorageClient localStorageClient) {
if (instance == null) {
instance = new CustomerRegistrationRepository(dataSource, localStorageClient);
instance = new CustomerContentRepository(dataSource, localStorageClient);
}
return instance;
}
@ -67,11 +71,16 @@ public class CustomerRegistrationRepository {
public Result<LoggedInUser> registerCustomer(ICustomer customer) {
// handle login
Result<LoggedInUser> result = dataSource.registerCustomer(customer);
Log.d(TAG, "START Customer Registration");
if (result instanceof Result.Success) {
Log.d(TAG, "Customer Registration success");
setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
}else{
Log.d(TAG, "-- Customer Registration ERROR", ((Result.Error)result).getError());
}
return result;
}
@ -82,7 +91,7 @@ public class CustomerRegistrationRepository {
return localStorageClient.loadVehicles();
}
public void storeCustomerVehicle(Vehicle vehicle) {
public void storeCustomerVehicle(Vehicle vehicle) throws Exception {
localStorageClient.storeVehicle(vehicle);
}
@ -92,22 +101,57 @@ public class CustomerRegistrationRepository {
//endregion
public Result<RegisteredVehicle> registerCustomerVehicle(Vehicle vehicle){
var customer = localStorageClient.loadCustomer();
if(customer.isPresent())
return registerCustomerVehicle(customer.get(), vehicle);
return new Result.Error(new Exception("NOT AUTHENTICATED"));
}
public Result<RegisteredVehicle> registerCustomerVehicle(ICustomer customer, Vehicle vehicle) {
public Result<RegisteredVehicle> registerCustomerVehicle(ICustomer customer, Vehicle vehicle)
{
// handle login
Result<RegisteredVehicle> result = dataSource.registerVehicle(customer, vehicle);
if (result instanceof Result.Success) {
localStorageClient.storeVehicle(((Result.Success<RegisteredVehicle>) result).getData().getVehicle());
// setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
try {
localStorageClient.storeVehicle(vehicle.getVin(), ((Result.Success<RegisteredVehicle>) result).getData().getVehicle());
} catch (Exception e) {
e.printStackTrace();
return new Result.Error(e);
}
// setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
}
return result;
}
public Result<List<Vehicle>> refreshCustomerVehicles() {
var result = dataSource.fetchCustomerVehicles(localStorageClient.getLoggedInUser());
if(result instanceof Result.Success){
var successResult = (Result.Success<List<Vehicle>>)result;
localStorageClient.storeVehicles(((Result.Success<List<Vehicle>>) result).getData());
}else{
}
return result;
}
public Result<List<Vehicle>> fetchCustomerVehiclesRemote() {
return dataSource
.fetchCustomerVehicles(localStorageClient.getLoggedInUser());
}
public void deleteCustomerVehicles() {
localStorageClient.deleteVehicles();
}
public void storeRemoteCustomerVehicles(List<Vehicle> items) {
localStorageClient.storeVehicles(items);
}
public List<CustomerDevice> getStoredUserDevices() {
return localStorageClient.loadDevices();
}
}

View File

@ -6,7 +6,9 @@ import eu.csc.vehown.data.model.LoggedInUser;
import eu.csc.vehown.data.model.Vehicle;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.services.rest.vehownserver.VehOwnApiClientFactory;
import eu.csc.vehown.ui.models.RegisteredVehicle;
import eu.csc.vehown.ui.models.Result;
import lombok.var;
import java.util.List;
@ -70,7 +72,7 @@ public class CustomerVehicleRegistrationRepository {
return localStorageClient.loadVehicles();
}
public void storeCustomerVehicle(Vehicle vehicle) {
public void storeCustomerVehicle(Vehicle vehicle) throws Exception {
localStorageClient.storeVehicle(vehicle);
}
@ -81,4 +83,23 @@ public class CustomerVehicleRegistrationRepository {
public void deleteCustomerVehicles() {
localStorageClient.deleteVehicles();
}
public Result<RegisteredVehicle> registerCustomerVehicle(Vehicle vehicle) {
try {
storeCustomerVehicle(vehicle);
} catch (Exception e) {
e.printStackTrace();
return new Result.Error(e);
}
Result<RegisteredVehicle> result = dataSource.registerVehicle(localStorageClient.getLoggedInUser(), vehicle);
if(result.isSuccess()){
//ToDo store Customer Vehicle on Smartphone
//setRegisteredVehicle(result.getSuccessBody());
}
return result;
}
}

View File

@ -1,11 +1,13 @@
package eu.csc.vehown.ui.registration.device;
import android.content.Context;
import android.text.Editable;
import androidx.lifecycle.MutableLiveData;
import java.io.IOException;
import eu.csc.ODPAppVehOwnServer.models.data.DeviceArticleDto;
import eu.csc.vehown.data.model.CustomerDevice;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.services.rest.vehownserver.VehOwnApiClientFactory;
@ -20,15 +22,19 @@ public class DeviceRegistrationViewModel extends AbstractBaseViewModel {
@Getter
private final MutableLiveData<String> mSerialnumber;
@Getter
private final MutableLiveData<CustomerDevice> mCustomerDevice;
@Getter
private final MutableLiveData<Boolean> mIsEnabled;
@Getter
private final MutableLiveData<Result<CustomerDevice>> mRegistrationResult;
private final CustomerContentDataSource dataSource;
//private IVehOwnAppClient restClient;
@ -38,14 +44,13 @@ public class DeviceRegistrationViewModel extends AbstractBaseViewModel {
super(localStorage);
mSerialnumber = new MutableLiveData<>();
mIsEnabled = new MutableLiveData<>();
mRegistrationResult = new MutableLiveData<>();
mCustomerDevice = new MutableLiveData<>();
this.dataSource = dataSource;
mRegistrationResult = new MutableLiveData<>();
mSerialnumber.setValue(localStorage.getLastSerialnumber());
mCustomerDevice = new MutableLiveData<>();
}
@ -57,25 +62,24 @@ public class DeviceRegistrationViewModel extends AbstractBaseViewModel {
executorService.execute(new Runnable() {
@Override
public void run() {
//ToDo add
//ToDo add
Result<CustomerDevice> result = null;
try {
localStorageClient.storeSerialnumber(getMSerialnumber().getValue());
var restClient = VehOwnApiClientFactory.getAuthenticatedDataClient(localStorageClient.getLoggedInUser());
var response = restClient.registerCustomerDevice(getMSerialnumber().getValue()).execute();
CustomerDevice item = new CustomerDevice();
item.setSerialNumber(response.body().getSerialNumber());
item.setDeviceNumber(response.body().getDeviceNumber());
item.setName(response.body().getName());
result = new Result.Success(item);
var restClient = VehOwnApiClientFactory.getAuthenticatedDataClient(localStorageClient.getLoggedInUser());
var response = restClient.registerCustomerDevice(getMSerialnumber().getValue()).execute();
CustomerDevice item = new CustomerDevice();
item.setSerialNumber(response.body().getSerialNumber());
item.setDeviceNumber(response.body().getDeviceNumber());
item.setName(response.body().getName());
result = new Result.Success(item);
//response.
} catch (IOException e) {
} catch (IOException e) {
e.printStackTrace();
result = new Result.Error(e);
}
@ -85,18 +89,50 @@ public class DeviceRegistrationViewModel extends AbstractBaseViewModel {
});
}
public void storeDevice() {
CustomerDevice item = new CustomerDevice();
item.setDeviceNumber(getMSerialnumber().getValue());
item.setSerialNumber(getMSerialnumber().getValue());
item.setName(getMSerialnumber().getValue());
getMIsEnabled().postValue(false);
executorService.execute(new Runnable() {
@Override
public void run() {
try {
localStorageClient.storeDevice(mCustomerDevice.getValue());
getMIsEnabled().postValue(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void findDeviceBySerialnumber(String serialnumber) {
getMIsEnabled().postValue(false);
executorService.execute(new Runnable() {
@Override
public void run() {
var result = dataSource.fetchCustomerDevice(localStorageClient.getLoggedInUser(), serialnumber);
if (result instanceof Result.Success) {
var successResult = ((Result.Success<DeviceArticleDto>) result).getData();
CustomerDevice item = new CustomerDevice();
item.setSerialNumber(successResult.getSerialnumber());
item.setDeviceNumber(successResult.getDevice().getDeviceNumber());
item.setName(successResult.getDevice().getName());
getMCustomerDevice().postValue(item);
} else {
}
getMIsEnabled().postValue(true);
}
});
localStorageClient.storeDevice(item);
}
}

View File

@ -11,7 +11,7 @@ import eu.csc.vehown.data.model.LoggedInUser;
import eu.csc.vehown.ui.models.LoggedInUserView;
import eu.csc.vehown.ui.models.LoginFormState;
import eu.csc.vehown.ui.models.LoginResult;
import eu.csc.vehown.ui.registration.data.CustomerRegistrationRepository;
import eu.csc.vehown.ui.registration.data.CustomerContentRepository;
import eu.csc.vehown.ui.models.Result;
import java.util.concurrent.ExecutorService;
@ -26,9 +26,9 @@ public class CustomerRegistrationViewModel extends ViewModel {
private MutableLiveData<LoginResult> loginResult = new MutableLiveData<>();
private CustomerRegistrationRepository registrationRepository;
private CustomerContentRepository registrationRepository;
public CustomerRegistrationViewModel(CustomerRegistrationRepository registrationRepository) {
public CustomerRegistrationViewModel(CustomerContentRepository registrationRepository) {
this.registrationRepository = registrationRepository;
}

View File

@ -17,10 +17,12 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.DatePicker;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import eu.csc.vehown.R;
import eu.csc.vehown.data.model.Vehicle;
import eu.csc.vehown.data.model.VehicleBrand;
@ -134,7 +136,7 @@ public class VehicleRegistrationFragment extends Fragment {
final View.OnFocusChangeListener focusListener = (v, hasFocus) -> delayHidingKeyboard(3000);
final TextChangedListener changedListener = new TextChangedListener(() -> {
delayHidingKeyboard((3000));
delayHidingKeyboard((3000));
Helper.enableButton(binding.btnRegisterVehicle, mandatoryFields);
});
Helper.addListener(mandatoryFields, focusListener, changedListener);
@ -191,9 +193,7 @@ public class VehicleRegistrationFragment extends Fragment {
binding.btnRegisterVehicle.setOnClickListener(v -> {
Vehicle vehicle = getVehicle();
viewModel
.getRepository()
.storeCustomerVehicle(vehicle);
viewModel.registerCustomerVehicle(vehicle);
//ToDo run RestCall
@ -296,13 +296,19 @@ public class VehicleRegistrationFragment extends Fragment {
private Vehicle getVehicle() {
Vehicle vehicle = new Vehicle();
vehicle.setOld_vin(viewModel.getCurrentVehicleVin());
vehicle.setBitmap(bitmap);
vehicle.setBrand(((VehicleBrand) binding.spBrand.getSelectedItem()).getName());
if (binding.spBrand.getSelectedItem() != null)
vehicle.setBrand(((VehicleBrand) binding.spBrand.getSelectedItem()).getName());
if (binding.spModel.getSelectedItem() != null)
vehicle.setModel(((VehicleModel) binding.spModel.getSelectedItem()).getName());
vehicle.setPowertrain(binding.editPowertrain.getText().toString());
vehicle.setVariant(binding.editVariant.getText().toString());
vehicle.setVin(binding.editVIN.getText().toString());
vehicle.setLicensePlate(binding.editLicensePlate.getText().toString());
if (binding.spPropulsion.getSelectedItem() != null)
vehicle.setPropulsionType(((VehiclePropulsionType) binding.spPropulsion.getSelectedItem()).getName());
vehicle.setRegistrationDate((Date) binding.editRegistrationDate.getTag());

View File

@ -3,11 +3,12 @@ package eu.csc.vehown.ui.registration.vehicle;
import android.content.Context;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import eu.csc.log.Log;
import eu.csc.vehown.data.model.Vehicle;
import eu.csc.vehown.data.model.VehicleBrand;
import eu.csc.vehown.data.model.VehicleModel;
@ -15,18 +16,18 @@ import eu.csc.vehown.data.model.VehiclePropulsionType;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.services.rest.vehownserver.VehOwnApiClientFactory;
import eu.csc.vehown.ui.modal.Helper;
import eu.csc.vehown.ui.models.RegisteredVehicle;
import eu.csc.vehown.ui.models.Result;
import eu.csc.vehown.ui.registration.data.CustomerContentDataSource;
import eu.csc.vehown.ui.registration.data.CustomerRegistrationRepository;
import eu.csc.vehown.ui.registration.data.CustomerVehicleRegistrationRepository;
import eu.csc.vehown.ui.registration.data.CustomerContentRepository;
import eu.csc.vehown.ui.viewmodels.AbstractBaseViewModel;
import lombok.Getter;
import lombok.var;
public class VehicleRegistrationViewModel extends AbstractBaseViewModel {
private static final String TAG = VehicleRegistrationViewModel.class.getSimpleName();
@Getter
private final CustomerRegistrationRepository repository;
private final Context context;
private final CustomerContentRepository repository;
@Getter
private final MutableLiveData<List<VehicleBrand>> vehicleBrands;
@ -40,19 +41,20 @@ public class VehicleRegistrationViewModel extends AbstractBaseViewModel {
@Getter
private final MutableLiveData<Vehicle> currentVehicle;
@Getter
private final MutableLiveData<Result<RegisteredVehicle>> vehicleRegistrationResult;
public VehicleRegistrationViewModel(CustomerRegistrationRepository repository, Context context, LocalStorageClient localStorageClient) {
super(localStorageClient);
public VehicleRegistrationViewModel(CustomerContentRepository repository, Context context, LocalStorageClient localStorageClient) {
super(context);
vehicleBrands = new MutableLiveData<>();
vehiclePropulsionTypes = new MutableLiveData<>();
vehicleModels = new MutableLiveData<>();
logginResult = new MutableLiveData<>();
this.context = context;
this.repository = repository;
currentVehicle = new MutableLiveData<>();
vehicleRegistrationResult = new MutableLiveData<>();
}
public void fetchData() {
@ -106,12 +108,20 @@ public class VehicleRegistrationViewModel extends AbstractBaseViewModel {
}
public void storeVehicle(Vehicle vehicle) {
Helper.infoToast(context, "Storing vehicle data local");
getRepository().storeCustomerVehicle(vehicle);
Helper.infoToast(context, "success");
if (vehicle.getVin() == null) {
Helper.infoToast(context, "NEED VIN");
return;
}
try {
getRepository().storeCustomerVehicle(vehicle);
Helper.infoToast(context, "success");
} catch (Exception e) {
e.printStackTrace();
}
}
public void deleteVehicle(Vehicle vehicle) {
Helper.infoToast(context, "Deleting vehicle");
@ -122,4 +132,26 @@ public class VehicleRegistrationViewModel extends AbstractBaseViewModel {
public void unregisterVehicle() {
}
public void registerCustomerVehicle(Vehicle vehicle) {
Log.d(TAG, "REGISTERING VEHICLE");
executorService.execute(new Runnable() {
@Override
public void run() {
var result = repository
.registerCustomerVehicle(localStorageClient.getLoggedInUser(), vehicle);
vehicleRegistrationResult.postValue(result);
}
});
//getRepository().storeCustomerVehicle(vehicle);
}
public String getCurrentVehicleVin() {
if(getCurrentVehicle().getValue() != null)
return getCurrentVehicle().getValue().getVin();
return null;
}
}

View File

@ -1,5 +1,6 @@
package eu.csc.vehown.ui.viewmodels;
import android.content.Context;
import android.util.Patterns;
import androidx.lifecycle.ViewModel;
@ -7,12 +8,15 @@ import androidx.lifecycle.ViewModel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import eu.csc.log.Log;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
public abstract class AbstractBaseViewModel extends ViewModel {
protected final LocalStorageClient localStorageClient;
protected Context context;
protected ExecutorService executorService = Executors.newFixedThreadPool(4);
@ -20,6 +24,11 @@ public abstract class AbstractBaseViewModel extends ViewModel {
this.localStorageClient = localStorage;
}
protected AbstractBaseViewModel(Context context) {
this(SharedPreferencesFactory.getInstance(context, Log.getLogger("ViewModelBase")));
this.context = context;
}
protected boolean isUserNameValid(String username) {
if (username == null) {
return false;
@ -41,4 +50,9 @@ public abstract class AbstractBaseViewModel extends ViewModel {
protected boolean isPasswordValid(String password) {
return password != null && password.trim().length() > 5;
}
protected void d(String tag, String msg) {
Log.d(tag, msg);
}
}

View File

@ -5,15 +5,17 @@ import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.annotation.NonNull;
import eu.csc.log.Log;
import eu.csc.vehown.persist.sharedPreferences.LocalStorageClient;
import eu.csc.vehown.persist.sharedPreferences.SharedPreferencesFactory;
import eu.csc.vehown.ui.fragments.UserProfileViewModel;
import eu.csc.vehown.ui.fragments.data.LoginRepository;
import eu.csc.vehown.ui.fragments.ui.login.LoginViewModel;
import eu.csc.vehown.ui.registration.RegistrationViewModel;
import eu.csc.vehown.ui.registration.VehicleAndDevicesViewModel;
import eu.csc.vehown.ui.registration.customer.FragmentCustomerRegistrationViewModel;
import eu.csc.vehown.ui.registration.data.CustomerContentDataSource;
import eu.csc.vehown.ui.registration.data.CustomerRegistrationRepository;
import eu.csc.vehown.ui.registration.data.CustomerContentRepository;
import eu.csc.vehown.ui.registration.data.CustomerVehicleRegistrationRepository;
import eu.csc.vehown.ui.registration.device.DeviceRegistrationViewModel;
import eu.csc.vehown.ui.registration.login.CustomerRegistrationViewModel;
@ -39,7 +41,7 @@ public class AppViewModelFactory implements ViewModelProvider.Factory {
@Override
@SuppressWarnings("unchecked")
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
LocalStorageClient localStorage = SharedPreferencesFactory.getInstance(context);
LocalStorageClient localStorage = SharedPreferencesFactory.getInstance(context, Log.getLogger(this.getClass()));
@ -53,7 +55,7 @@ public class AppViewModelFactory implements ViewModelProvider.Factory {
localStorage);
}
if (modelClass.isAssignableFrom(CustomerRegistrationViewModel.class)) {
return (T) new CustomerRegistrationViewModel(CustomerRegistrationRepository.getInstance(
return (T) new CustomerRegistrationViewModel(CustomerContentRepository.getInstance(
new CustomerContentDataSource(),
localStorage));
}
@ -68,8 +70,13 @@ public class AppViewModelFactory implements ViewModelProvider.Factory {
else if(modelClass.isAssignableFrom(FragmentCustomerRegistrationViewModel.class)){
return (T) new FragmentCustomerRegistrationViewModel(localStorage, context, new CustomerContentDataSource());
}
else if(modelClass.isAssignableFrom(UserProfileViewModel.class)){
return (T) new UserProfileViewModel(localStorage,CustomerContentRepository.getInstance(
new CustomerContentDataSource(),
localStorage));
}
else if(modelClass.isAssignableFrom(VehicleRegistrationViewModel.class)){
return (T) new VehicleRegistrationViewModel(CustomerRegistrationRepository.getInstance(
return (T) new VehicleRegistrationViewModel(CustomerContentRepository.getInstance(
new CustomerContentDataSource(),
localStorage),context, localStorage);
}

View File

@ -1,43 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".ui.login.LoginActivity">
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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".ui.login.LoginActivity">
<FrameLayout
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu_customer_registration"/>
<!-- <FrameLayout-->
<!-- android:id="@+id/content_frame"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:layout_marginBottom="48dp"-->
<!-- />-->
<fragment
android:id="@+id/content_frame"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="48dp"
app:defaultNavHost="true"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/navigation_login"
/>
<Button
android:id="@+id/btnSwitchView"
android:enabled="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginStart="48dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="48dp"
android:text="@string/NO_TEXT"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintVertical_bias="0.2"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -9,6 +9,7 @@
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:background="?android:windowBackground"
tools:context="ui.registration.customer.FragmentCustomerRegistration">

View File

@ -9,6 +9,7 @@
android:paddingTop="@dimen/fragment_vertical_margin"
android:paddingRight="@dimen/fragment_horizontal_margin"
android:paddingBottom="@dimen/fragment_vertical_margin"
android:background="?android:windowBackground"
tools:context=".ui.fragments.ui.login.LoginFragment">
<EditText
@ -58,6 +59,22 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edPassword" />
<EditText
android:id="@+id/tvUser"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionDone"
android:inputType="text"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cbRemember"
/>
<LinearLayout
android:id="@+id/llLocalButtons"
@ -114,5 +131,5 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="cbRemember" />
app:constraint_referenced_ids="tvUser" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
android:background="?android:windowBackground"
tools:context=".ui.fragments.UserProfileFragment">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Media -->
<ImageView
android:layout_width="match_parent"
android:layout_height="194dp"
android:contentDescription="@string/content_card_description_vehicle"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_default_vehicle" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Title, secondary and supporting text -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/content_card_description_vehicle"
android:textAppearance="?attr/textAppearanceHeadline6" />
<TextView
android:id="@+id/tvVehicleUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/text_last_update"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary" />
<TextView
android:id="@+id/tvVehicleCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/text_vehicles_count"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary" />
</LinearLayout>
<!-- Buttons -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/btnVehicleRefresh"
style="?attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/action_refresh" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnVehicleDelete"
style="?attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_delete" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnVehicleShow"
style="?attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_show" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnVehicleAdd"
style="?attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_new" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single"
>
>
<item
android:id="@+id/nav_login"
android:icon="@drawable/ic_baseline_login_24"
@ -26,34 +26,34 @@
</group>
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_dashboard"
android:icon="@drawable/ic_baseline_dashboard_24"
android:title="@string/menu_dashboard"
android:onClick="menuItemOnClicked"
/>
<item
android:id="@+id/nav_register_user"
android:icon="@drawable/ic_register"
android:title="@string/register_user"
android:onClick="menuItemOnClicked"
/><item
android:id="@+id/nav_register_Customer"
android:icon="@drawable/ic_register"
android:title="@string/register_customer"
android:id="@+id/nav_dashboard"
android:icon="@drawable/ic_baseline_dashboard_24"
android:title="@string/menu_dashboard"
android:onClick="menuItemOnClicked"
/>
/>
<item
android:id="@+id/nav_register_base"
android:icon="@drawable/ic_register"
android:title="@string/registration"
android:onClick="menuItemOnClicked"
android:id="@+id/nav_register_user"
android:icon="@drawable/ic_register"
android:title="@string/register_user"
android:onClick="menuItemOnClicked"
/><item
android:id="@+id/nav_register_Customer"
android:icon="@drawable/ic_register"
android:title="@string/register_customer"
android:onClick="menuItemOnClicked"
/>
<item
android:id="@+id/nav_register_base"
android:icon="@drawable/ic_register"
android:title="@string/registration"
android:onClick="menuItemOnClicked"
/>
<item
android:id="@+id/nav_show_vehicles_devices"
android:icon="@drawable/ic_register"
android:title="@string/vehicles_and_devices"
/>
android:id="@+id/nav_show_vehicles_devices"
android:icon="@drawable/ic_register"
android:title="@string/vehicles_and_devices"
/>
<!--item
android:id="@+id/nav_register_vehicle"
android:icon="@drawable/ic_register"
@ -67,31 +67,31 @@
android:onClick="menuItemOnClicked"
/-->
<item
android:id="@+id/nav_downloaded_events"
android:icon="@drawable/ic_baseline_event_note_24"
android:title="@string/menu_downloaded_events"
android:onClick="menuItemOnClicked"
/>
android:id="@+id/nav_downloaded_events"
android:icon="@drawable/ic_baseline_event_note_24"
android:title="@string/menu_downloaded_events"
android:onClick="menuItemOnClicked"
/>
<item
android:id="@+id/nav_reported_events"
android:icon="@drawable/ic_baseline_archive_24"
android:title="@string/menu_reported_events"
android:id="@+id/nav_reported_events"
android:icon="@drawable/ic_baseline_archive_24"
android:title="@string/menu_reported_events"
/>
/>
<item
android:id="@+id/nav_settings"
android:icon="@drawable/ic_settings"
android:title="@string/menu_settings"
android:onClick="menuItemOnClicked"
/>
android:id="@+id/nav_settings"
android:icon="@drawable/ic_settings"
android:title="@string/menu_settings"
android:onClick="menuItemOnClicked"
/>
<item
android:id="@+id/nav_svivehicles"
android:icon="@drawable/ic_baseline_directions_car_24"
android:title="@string/menu_svivehicles"
android:onClick="menuItemOnClicked"
/>
android:id="@+id/nav_svivehicles"
android:icon="@drawable/ic_baseline_directions_car_24"
android:title="@string/menu_svivehicles"
android:onClick="menuItemOnClicked"
/>
</group>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_customer_register_login"
android:icon="@drawable/ic_baseline_how_to_reg_24"
android:title="@string/title_login"/>
<item
android:id="@+id/navigation_customer_register_register"
android:icon="@drawable/ic_baseline_how_to_reg_24"
android:title="@string/title_register_customer"/>
<item
android:id="@+id/navigation_customer_register_profile"
android:icon="@drawable/ic_baseline_how_to_reg_24"
android:title="@string/title_customer_profile"/>
</menu>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/navigation_login"
app:startDestination="@id/navigation_customer_register_login">
<fragment
android:id="@+id/navigation_customer_register_login"
android:name="eu.csc.vehown.ui.fragments.ui.login.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login" />
<fragment
android:id="@+id/navigation_customer_register_register"
android:name="eu.csc.vehown.ui.registration.customer.FragmentCustomerRegistration"
android:label="fragment_customer_registration"
tools:layout="@layout/fragment_customer_registration_fragment" />
<fragment
android:id="@+id/navigation_customer_register_profile"
android:name="eu.csc.vehown.ui.fragments.UserProfileFragment"
android:label="fragment_user_profile"
tools:layout="@layout/user_profile_fragment" />
</navigation>

View File

@ -157,5 +157,15 @@
<string name="pref_offline_mode">pref_offline_mode</string>
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="content_card_description_vehicle">Vehicle</string>
<string name="text_last_update">Last Update %s</string>
<string name="text_vehicles_count">Vehicles: %s</string>
<string name="action_refresh">Refresh</string>
<string name="action_delete">Delete</string>
<string name="action_show">Show</string>
<string name="action_new">New</string>
<string name="title_login">Login</string>
<string name="title_register_customer">Register</string>
<string name="title_customer_profile">Profile</string>
</resources>

View File

@ -35,6 +35,7 @@ dependencies {
implementation 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
implementation 'com.google.code.gson:gson:2.9.0'
}

View File

@ -1,5 +1,6 @@
package eu.csc.vehown;
import android.content.Context;
import android.os.Environment;
import android.os.StatFs;
@ -39,4 +40,9 @@ public class Helper {
StatFs stats = new StatFs(Environment.getDataDirectory().getAbsolutePath());
return stats.getTotalBytes();
}
public static String getString(Context context, int text_id) {
return context.getResources().getString(text_id);
}
}

View File

@ -30,6 +30,7 @@ public class Customer implements Serializable, ICustomer {
this.street = customer.getStreet();
this.phone = customer.getPhone();
this.languageName = customer.getLanguage();
this.serverId = customer.getServerId();
}
@Override

View File

@ -11,4 +11,6 @@ public interface ICustomer {
String getPassword();
String getStreet();
String getLanguage();
Long getServerId();
}

View File

@ -25,13 +25,28 @@ public class LoggedInUser implements Serializable, ICustomer {
private String street;
private String password;
private String language;
private Long serverId;
public LoggedInUser(String userId, String displayName) {
this.userId = userId;
public LoggedInUser(Long userId, String displayName) {
this.userId = ""+ userId;
this.serverId = userId;
this.displayName = displayName;
}
public LoggedInUser(Long userId, ICustomer customer) {
this.userId = userId.toString();
this.serverId = userId;
this.login = customer.getEmail();
this.city = customer.getCity();
this.street = customer.getStreet();
this.lastname = customer.getLastname();
this.firstname = customer.getFirstname();
this.language= customer.getLanguage();
this.phone= customer.getPhone();
this.password = customer.getPassword();
}
public LoggedInUser(String firstname, String lastname, String login, String token) {
this.token = token;
this.firstname = firstname;

View File

@ -3,6 +3,9 @@ package eu.csc.vehown.data.model;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import com.google.gson.annotations.Expose;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -29,7 +32,7 @@ public class Vehicle implements Serializable {
private String propulsionType;
private Date registrationDate;
@Expose(serialize = false, deserialize = false)
private String old_vin;
public void refreshContent(Vehicle item) {
@ -50,9 +53,12 @@ public class Vehicle implements Serializable {
/**
* Converts a bitmap into a BASE64 encoded string.
*
* @param bitmap
*/
public void setBitmap(Bitmap bitmap) {
if (bitmap == null)
return;
final int COMPRESSION_QUALITY = 100;
ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, byteArrayBitmapStream);
@ -66,10 +72,18 @@ public class Vehicle implements Serializable {
/**
* Retrieves the bitmap from the BASE64 encoded string.
*
* @return the bitmap
*/
public Bitmap getBitmap() {
if (bitmapString == null) return null;
if (bitmapString == null)
return null;
byte[] decodedString = Base64.decode(bitmapString, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
}}
}
public String getStoredVin() {
return old_vin == null ? null : old_vin;
}
}

View File

@ -0,0 +1,8 @@
package eu.csc.vehown.log;
public interface ILogger {
void d(String msg);
void d(String tag, String msg);
}

View File

@ -25,6 +25,12 @@ public interface EntityLogDao extends BaseDao<EntityLog> {
" ORDER BY time DESC")
List<EntityLog> getLogs(long from, Integer type);
@Query("SELECT * FROM log" +
" WHERE time > :from" +
" ORDER BY time DESC")
List<EntityLog> getLogs(long from);
@Insert
long insertLog(EntityLog log);
@ -32,5 +38,10 @@ public interface EntityLogDao extends BaseDao<EntityLog> {
" WHERE id IN (SELECT id FROM log" +
" WHERE time < :before ORDER BY time LIMIT :limit)")
int deleteLogs(long before, int limit);
@Query("SELECT COUNT(id) FROM log" +
" WHERE id IN (SELECT id FROM log" +
" WHERE time < :before ORDER BY time LIMIT :limit)")
int countDeleteLogs(long before, int limit);
}

View File

@ -29,11 +29,11 @@ public interface LocalStorageClient extends IVehOwnData {
List<Vehicle> loadVehicles();
void storeVehicle(Vehicle vehicle);
void storeVehicle(Vehicle vehicle) throws Exception;
void deleteVehicle(Vehicle vehicle);
List<CustomerDevice> loadDevices();
void storeDevice(CustomerDevice vehicle);
void storeDevice(CustomerDevice vehicle) throws Exception;
@ -53,6 +53,12 @@ public interface LocalStorageClient extends IVehOwnData {
void deleteDevice(String serialNumber);
void deleteDevices();
void storeVehicles(List<Vehicle> items);
void storeVehicle(String vin, Vehicle vehicle) throws Exception;
//region ServerData

View File

@ -9,6 +9,7 @@ import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import eu.csc.vehown.data.model.*;
import eu.csc.vehown.log.ILogger;
import eu.csc.vehown.persist.localstorage.R;
import lombok.var;
@ -32,19 +33,20 @@ public class LocalStorageClientImpl implements LocalStorageClient {
private static final String PREF_CUSTOMER = "customer";
private static final String PREF_VEHICLES = "vehicles";
private static final String PREF_DEVICES = "devices";
private final ILogger logger;
// private static final String KEY_LOGGEDINUSERNAME = "prefs_loggedin_username";
private File tokenDir;
private File eventsDir;
private String TAG = LocalStorageClientImpl.class.getSimpleName();
private static final String TAG = LocalStorageClientImpl.class.getSimpleName();
public static LocalStorageClientImpl getInstance(Context context) {
return new LocalStorageClientImpl(context);
public static LocalStorageClientImpl getInstance(Context context, ILogger logger) {
return new LocalStorageClientImpl(context, logger);
}
protected LocalStorageClientImpl(Context context) {
protected LocalStorageClientImpl(Context context, ILogger logger) {
this.logger = logger;
this.sharedPreferences = context.getSharedPreferences(
context.getString(R.string.preference_file_key), Context.MODE_PRIVATE);
@ -102,15 +104,18 @@ public class LocalStorageClientImpl implements LocalStorageClient {
if (customer == null) {
} else {
if(customer instanceof Customer){
value = gson.toJson((Customer)customer);
}else{
if (customer instanceof Customer) {
value = gson.toJson((Customer) customer);
} else {
value = gson.toJson(new Customer(customer));
}
}
sharedPreferences.edit().putString(PREF_CUSTOMER, value);
sharedPreferences
.edit()
.putString(PREF_CUSTOMER, value)
.apply();
}
@ -145,10 +150,22 @@ public class LocalStorageClientImpl implements LocalStorageClient {
}
@Override
public void storeVehicle(Vehicle vehicle) {
public void storeVehicle(Vehicle vehicle) throws Exception {
if (vehicle == null || vehicle.getVin() == null) {
throw new Exception("NO VIN");
}
var vehicles = loadVehicles();
for (int i = 0; i < vehicles.size(); i++) {
if (vehicle.equalsIdentification(vehicles.get(i))) {
boolean found = false;
if (vehicle.getOld_vin() != null) {
if (vehicle.getOld_vin().equals(vehicles.get(i).getVin())) {
found = true;
}
} else if (vehicle.equalsIdentification(vehicles.get(i))) {
found = true;
}
if (found) {
vehicles.set(i, vehicle);
getEditor().putString(PREF_VEHICLES, gson.toJson(vehicles)).apply();
return;
@ -186,8 +203,10 @@ public class LocalStorageClientImpl implements LocalStorageClient {
}
@Override
public void storeDevice(CustomerDevice item) {
public void storeDevice(CustomerDevice item) throws Exception {
if (item == null || item.getSerialNumber() == null) {
throw new Exception("NO IDENTIFIER");
}
var items = loadDevices();
for (int i = 0; i < items.size(); i++) {
if (item.getSerialNumber().equals(items.get(i).getSerialNumber())) {
@ -257,6 +276,38 @@ public class LocalStorageClientImpl implements LocalStorageClient {
}
}
@Override
public void deleteDevices() {
Log.d(TAG, "DELETE DEVICES");
storeDevices(null);
}
public void storeDevices(List<CustomerDevice> items) {
String json = null;
if (items != null) {
Log.d(TAG, "Storing Devices:");
json = getJsonString(items);
}
getEditor()
.putString(PREF_DEVICES, json)
.apply();
}
@Override
public void storeVehicles(List<Vehicle> items) {
getEditor().putString(PREF_VEHICLES, gson.toJson(items)).apply();
}
@Override
public void storeVehicle(String vin, Vehicle vehicle) throws Exception {
vehicle.setOld_vin(vin);
storeVehicle(vehicle);
}
private SharedPreferences.Editor getEditor() {
return sharedPreferences.edit();
}
@ -281,14 +332,26 @@ public class LocalStorageClientImpl implements LocalStorageClient {
SharedPreferences.Editor editor = getEditor();
editor.putString(KEY_LOGGEDINUSER, content);
editor.apply();
editor.putString(KEY_LOGGEDINUSER, content).apply();
setIsLoggedIn(true);
}
public void doLogout() {
d("Do Logout");
this.setIsLoggedIn(false);
this.setLoggedInUser(LoggedInUser.getEmptyUser());
this.deleteVehicles();
this.deleteDevices();
}
private void d(String msg) {
if (logger != null)
logger.d(TAG, msg);
else {
Log.d(TAG, msg);
}
}
@ -296,7 +359,7 @@ public class LocalStorageClientImpl implements LocalStorageClient {
String loggedInUser = sharedPreferences.getString(KEY_LOGGEDINUSER, null);
Log.d(TAG, loggedInUser);
Log.d(TAG, loggedInUser == null ? "" : loggedInUser);
if (loggedInUser == null) {
return null;
}

View File

@ -2,15 +2,21 @@ package eu.csc.vehown.persist.sharedPreferences;
import android.content.Context;
import eu.csc.vehown.log.ILogger;
public class SharedPreferencesFactory {
public static LocalStorageClient getInstance(Context context, ILogger logger){
return new LocalStorageClientImpl(context, logger);
}
public static LocalStorageClient getInstance(Context context){
return new LocalStorageClientImpl(context);
return new LocalStorageClientImpl(context, null);
}
public static boolean isLoggedIn(Context context){
return getInstance(context).getIsLoggedIn();
return getInstance(context, null).getIsLoggedIn();
}
}