/**
* Odoo, Open Source Management Solution
* Copyright (C) 2012-today Odoo SA (<http:www.odoo.com>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http:www.gnu.org/licenses/>
*
* Created on 13/1/15 11:19 AM
*/
package com.odoo.addons.phonecall;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;
import com.odoo.R;
import com.odoo.addons.phonecall.models.CRMPhoneCalls;
import com.odoo.base.addons.res.ResPartner;
import com.odoo.core.orm.ODataRow;
import com.odoo.core.orm.OValues;
import com.odoo.core.orm.fields.OColumn;
import com.odoo.core.support.addons.fragment.BaseFragment;
import com.odoo.core.support.addons.fragment.IOnSearchViewChangeListener;
import com.odoo.core.support.addons.fragment.ISyncStatusObserverListener;
import com.odoo.core.support.drawer.ODrawerItem;
import com.odoo.core.support.list.IOnItemClickListener;
import com.odoo.core.support.list.OCursorListAdapter;
import com.odoo.core.utils.IntentUtils;
import com.odoo.core.utils.OControls;
import com.odoo.core.utils.OCursorUtils;
import com.odoo.core.utils.ODateUtils;
import com.odoo.core.utils.OResource;
import com.odoo.core.utils.dialog.OChoiceDialog;
import com.odoo.core.utils.sys.IOnBackPressListener;
import com.odoo.widgets.bottomsheet.BottomSheet;
import com.odoo.widgets.bottomsheet.BottomSheetListeners;
import com.odoo.widgets.snackbar.SnackBar;
import com.odoo.widgets.snackbar.SnackbarBuilder;
import com.odoo.widgets.snackbar.listeners.EventListener;
import java.util.ArrayList;
import java.util.List;
public class PhoneCalls extends BaseFragment implements
OCursorListAdapter.OnViewBindListener, LoaderManager.LoaderCallbacks<Cursor>,
SwipeRefreshLayout.OnRefreshListener, IOnSearchViewChangeListener,
View.OnClickListener, ISyncStatusObserverListener,
BottomSheetListeners.OnSheetItemClickListener, BottomSheetListeners.
OnSheetActionClickListener,
BottomSheetListeners.OnSheetMenuCreateListener, IOnItemClickListener, IOnBackPressListener, EventListener {
public static final String TAG = PhoneCalls.class.getSimpleName();
private View mView;
private ListView mList;
private OCursorListAdapter mAdapter;
private String mFilter = null;
private boolean syncRequested = false;
private BottomSheet mSheet = null;
public enum Type {
Logged, Scheduled
}
private Type mType = Type.Logged;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
return inflater.inflate(R.layout.common_listview, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mView = view;
mType = Type.valueOf(getArguments().getString("type"));
setHasSwipeRefreshView(mView, R.id.swipe_container, this);
initAdapter();
}
private void initAdapter() {
mList = (ListView) mView.findViewById(R.id.listview);
mAdapter = new OCursorListAdapter(getActivity(), null, R.layout.phonecall_item);
mAdapter.setOnViewBindListener(this);
mList.setAdapter(mAdapter);
parent().setOnBackPressListener(this);
setHasFloatingButton(mView, R.id.fabButton, mList, this);
setHasSyncStatusObserver(TAG, this, db());
mAdapter.handleItemClickListener(mList, this);
getLoaderManager().initLoader(0, null, this);
}
@Override
public void onViewBind(View view, Cursor cursor, ODataRow row) {
OControls.setText(view, R.id.name, row.getString("name"));
String date = ODateUtils.convertToDefault(row.getString("date"),
ODateUtils.DEFAULT_FORMAT, "MMM, dd hh:mm a");
OControls.setText(view, R.id.date, date);
OControls.setText(view, R.id.state, db().getLabel("state", row.getString("state")));
if (!row.getString("description").equals("false")) {
OControls.setVisible(view, R.id.description);
OControls.setText(view, R.id.description, row.getString("description"));
} else {
OControls.setGone(view, R.id.description);
}
if (!row.getString("customer_name").equals("")) {
OControls.setVisible(view, R.id.customer_name);
OControls.setText(view, R.id.customer_name, row.getString("customer_name"));
} else {
OControls.setGone(view, R.id.customer_name);
}
if (row.getString("call_type").equals("false")) {
OControls.setGone(view, R.id.call_type_icon);
} else {
OControls.setVisible(view, R.id.call_type_icon);
if (row.getString("call_type").equals("Inbound")) {
OControls.setImage(view, R.id.call_type_icon, R.drawable.ic_action_call_inbound);
} else {
OControls.setImage(view, R.id.call_type_icon, R.drawable.ic_action_call_outbound);
}
}
if (row.getString("lead_name").equals("")) {
OControls.setGone(view, R.id.lead_name);
} else {
OControls.setVisible(view, R.id.lead_name);
OControls.setText(view, R.id.lead_name, row.getString("lead_name"));
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle data) {
String where;
List<String> args = new ArrayList<>();
if (mType == Type.Logged) {
where = " state = ?";
args.add("done");
} else {
where = " state != ?";
args.add("done");
}
if (mFilter != null) {
where += " and name like ? or lead_name like ? or customer_name like ?";
args.add("%" + mFilter + "%");
args.add("%" + mFilter + "%");
args.add("%" + mFilter + "%");
}
return new CursorLoader(getActivity(), db().uri(), null, where,
(args.size() > 0) ? args.toArray(new String[args.size()]) : null, "date");
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.changeCursor(data);
if (data.getCount() > 0) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
OControls.setGone(mView, R.id.loadingProgress);
OControls.setVisible(mView, R.id.swipe_container);
OControls.setGone(mView, R.id.customer_no_items);
setHasSwipeRefreshView(mView, R.id.swipe_container, PhoneCalls.this);
}
}, 500);
} else {
if (db().isEmptyTable() && !syncRequested) {
syncRequested = true;
onRefresh();
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
OControls.setGone(mView, R.id.loadingProgress);
OControls.setGone(mView, R.id.swipe_container);
OControls.setVisible(mView, R.id.customer_no_items);
setHasSwipeRefreshView(mView, R.id.customer_no_items, PhoneCalls.this);
OControls.setImage(mView, R.id.icon, R.drawable.ic_action_customers);
if (mType == Type.Logged) {
OControls.setText(mView, R.id.title, _s(R.string.label_no_logged_calls_found));
OControls.setImage(mView, R.id.icon,R.drawable.ic_action_call_logs);
} else {
OControls.setText(mView, R.id.title, _s(R.string.label_no_scheduled_calls_found));
OControls.setImage(mView, R.id.icon,R.drawable.ic_action_schedule_call);
}
OControls.setText(mView, R.id.subTitle, "");
}
}, 500);
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.changeCursor(null);
}
@Override
public List<ODrawerItem> drawerMenus(Context context) {
List<ODrawerItem> menu = new ArrayList<>();
menu.add(new ODrawerItem(TAG)
.setTitle(OResource.string(context, R.string.label_phone_calls))
.setGroupTitle());
menu.add(new ODrawerItem(TAG)
.setTitle(OResource.string(context, R.string.label_logged_calls))
.setIcon(R.drawable.ic_action_call_logs)
.setExtra(extra(Type.Logged))
.setInstance(new PhoneCalls()));
menu.add(new ODrawerItem(TAG)
.setTitle(OResource.string(context, R.string.label_scheduled_calls))
.setIcon(R.drawable.ic_action_schedule_call)
.setExtra(extra(Type.Scheduled))
.setInstance(new PhoneCalls()));
return menu;
}
private Bundle extra(Type type) {
Bundle extra = new Bundle();
extra.putString("type", type.toString());
return extra;
}
@Override
public Class<CRMPhoneCalls> database() {
return CRMPhoneCalls.class;
}
@Override
public void onRefresh() {
if (inNetwork()) {
parent().sync().requestSync(CRMPhoneCalls.AUTHORITY);
setSwipeRefreshing(true);
} else {
hideRefreshingProgress();
Toast.makeText(getActivity(), _s(R.string.toast_network_required), Toast.LENGTH_LONG)
.show();
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.menu_phonecalls, menu);
setHasSearchView(this, menu, R.id.menu_phonecall_search);
}
@Override
public boolean onSearchViewTextChange(String newFilter) {
mFilter = newFilter;
getLoaderManager().restartLoader(0, null, this);
return true;
}
@Override
public void onSearchViewClose() {
//Nothing to do
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.fabButton:
IntentUtils.startActivity(getActivity(), PhoneCallDetail.class, null);
break;
}
}
@Override
public void onStatusChange(Boolean refreshing) {
getLoaderManager().restartLoader(0, null, this);
}
// @Override
// public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// ODataRow row = OCursorUtils.toDatarow((Cursor) mAdapter.getItem(position));
// IntentUtils.startActivity(getActivity(), PhoneCallDetail.class, row.getPrimaryBundleData());
// }
@Override
public void onItemClick(BottomSheet sheet, MenuItem menu, Object extras) {
dismissSheet(sheet);
actionEvent(menu, (Cursor) extras);
}
@Override
public void onItemDoubleClick(View view, int position) {
ODataRow row = OCursorUtils.toDatarow((Cursor) mAdapter.getItem(position));
IntentUtils.startActivity(getActivity(), PhoneCallDetail.class, row.getPrimaryBundleData());
}
@Override
public void onItemClick(View view, int position) {
Cursor cr = (Cursor) mAdapter.getItem(position);
showSheet(cr);
}
private void showSheet(Cursor data) {
if (mSheet != null) {
mSheet.dismiss();
}
BottomSheet.Builder builder = new BottomSheet.Builder(getActivity());
builder.listener(this);
builder.setIconColor(_c(R.color.body_text_2));
builder.setTextColor(_c(R.color.body_text_1));
builder.setData(data);
builder.actionListener(this);
builder.setActionIcon(R.drawable.ic_action_edit);
builder.title(data.getString(data.getColumnIndex("name")));
builder.setOnSheetMenuCreateListener(this);
builder.menu(R.menu.menu_dashboard_phonecalls);
mSheet = builder.create();
mSheet.show();
}
private void actionEvent(MenuItem menu, Cursor cr) {
String is_done = cr.getString(cr.getColumnIndex("is_done"));
final OValues values = new OValues();
values.put("_is_dirty", "false"); // to ignore update on server
final int row_id = cr.getInt(cr.getColumnIndex(OColumn.ROW_ID));
values.put("is_done", (is_done.equals("0")) ? 1 : 0);
String done_label = (is_done.equals("0")) ? "done" : "undone";
final ODataRow row = OCursorUtils.toDatarow(cr);
Bundle data = row.getPrimaryBundleData();
switch (menu.getItemId()) {
case R.id.menu_phonecall_call:
int partner_id = cr.getInt(cr.getColumnIndex("partner_id"));
if (partner_id != 0) {
String contact = ResPartner.getContact(getActivity(), partner_id);
if (contact != null && !contact.equals("false")) {
IntentUtils.requestCall(getActivity(), contact);
} else {
Toast.makeText(getActivity(), _s(R.string.label_no_contact_found),
Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(getActivity(), _s(R.string.label_no_contact_found),
Toast.LENGTH_LONG).show();
}
break;
case R.id.menu_phonecall_reschedule:
List<String> choices = new ArrayList<>();
choices = new ArrayList<>();
choices.add("Re-Schedule call");
choices.add("Schedule other call");
OChoiceDialog.get(getActivity()).withOptions(choices, -1)
.show(new OChoiceDialog.OnChoiceSelectListener() {
@Override
public void choiceSelected(int position, String value) {
switch (position) {
case 0: // Re-Schedule
IntentUtils.startActivity(getActivity(), PhoneCallDetail.class,
row.getPrimaryBundleData());
break;
case 1: // Schedule other call
Bundle extra = row.getPrimaryBundleData();
extra.putInt("call_id", row.getInt(OColumn.ROW_ID));
IntentUtils.startActivity(getActivity(), PhoneCallDetail.class,
extra);
break;
}
}
});
break;
// All done menu
case R.id.menu_phonecall_all_done:
final CRMPhoneCalls phone_call = new CRMPhoneCalls(getActivity(), null);
values.put("state", "done");
phone_call.update(row_id, values);
getLoaderManager().restartLoader(0, null, this);
SnackBar.get(getActivity()).text(_s(R.string.toast_phone_call_marked_done))
.duration(SnackbarBuilder.SnackbarDuration.LENGTH_LONG)
.withEventListener(this).show();
break;
}
}
private void dismissSheet(final BottomSheet sheet) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
sheet.dismiss();
}
}, 100);
}
@Override
public void onShow(int i) {
hideFab();
}
@Override
public void onDismiss(int i) {
showFab();
}
@Override
public void onSheetActionClick(BottomSheet sheet, final Object extras) {
sheet.dismiss();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Cursor cr = (Cursor) extras;
String data_type = cr.getString(cr.getColumnIndex("data_type"));
int record_id = cr.getInt(cr.getColumnIndex(OColumn.ROW_ID));
Bundle extra = new Bundle();
extra.putInt(OColumn.ROW_ID, record_id);
IntentUtils.startActivity(getActivity(), PhoneCallDetail.class, extra);
}
}, 250);
}
@Override
public void onSheetMenuCreate(Menu menu, Object o) {
if (mType == Type.Logged)
menu.findItem(R.id.menu_phonecall_all_done).setVisible(false);
}
@Override
public boolean onBackPressed() {
if (mSheet != null && mSheet.isShowing()) {
mSheet.dismiss();
return false;
}
return true;
}
}