diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml
index 7201c639..38486851 100644
--- a/.github/workflows/cicd.yml
+++ b/.github/workflows/cicd.yml
@@ -7,18 +7,18 @@ on:
- development
jobs:
publish:
- name: CI/CD
+ name: CI/CD
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: 12.x
- - uses: microsoft/variable-substitution@v1
- with:
- files: './app.json'
- env:
- expo.hooks.postPublish.0.config.authToken: ${{ secrets.SENTRY_AUTH_TOKEN }}
+ #- uses: microsoft/variable-substitution@v1
+ # with:
+ # files: './app.json'
+ # env:
+ # expo.hooks.postPublish.0.config.authToken: ${{ secrets.SENTRY_AUTH_TOKEN }}
- uses: microsoft/variable-substitution@v1
with:
files: './google-services.json'
diff --git a/App.js b/App.js
index 89a030ba..c2243593 100644
--- a/App.js
+++ b/App.js
@@ -8,8 +8,8 @@ import * as Font from 'expo-font';
import { Asset } from 'expo-asset';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
-import Reactotron from 'reactotron-react-native';
-import * as Sentry from 'sentry-expo';
+//import Reactotron from 'reactotron-react-native';
+//import * as Sentry from 'sentry-expo';
import AppNavigator from './navigation/AppNavigator';
import { store, persistor } from './store/store';
@@ -19,11 +19,11 @@ import sharedTools from './shared';
import { setNetworkConnectivity } from './store/actions/networkConnectivity.actions';
-Sentry.init({
+/*Sentry.init({
dsn: 'https://aaa9d833ba5942d59c69e290ffbd3f36@o424480.ingest.sentry.io/5356329',
enableInExpoDevelopment: true,
debug: true,
-});
+});*/
// Styles
const styles = StyleSheet.create({
@@ -59,9 +59,9 @@ class App extends React.Component {
// If Reactotron gets no connection, this is the solution that worked for me (cairocoder01: 2019-08-15)
// https://github.com/expo/expo-cli/issues/153#issuecomment-358925525
// May need to then run this before `npm start`: `adb reverse tcp:9090 tcp:9090`
- Reactotron.configure() // controls connection & communication settings
- .useReactNative() // add all built-in react native plugins
- .connect(); // let's connect!
+ //Reactotron.configure() // controls connection & communication settings
+ // .useReactNative() // add all built-in react native plugins
+ // .connect(); // let's connect!
}
// Handle notifications that are received or selected while the app
diff --git a/app.json b/app.json
index f671e76e..2261f972 100644
--- a/app.json
+++ b/app.json
@@ -4,7 +4,7 @@
"slug": "discipletoolsapp",
"privacy": "public",
"platforms": ["ios", "android"],
- "version": "1.6.0",
+ "version": "1.7.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"splash": {
@@ -23,20 +23,8 @@
"android": {
"package": "tools.disciple.app",
"googleServicesFile": "./google-services.json",
- "versionCode": 160
+ "versionCode": 170
},
- "description": "",
- "hooks": {
- "postPublish": [
- {
- "file": "sentry-expo/upload-sourcemaps",
- "config": {
- "organization": "Disciple Tools",
- "project": "DT Mobile",
- "authToken": ""
- }
- }
- ]
- }
+ "description": ""
}
}
diff --git a/constants/Colors.js b/constants/Colors.js
index 810a9ebd..4aeea22a 100644
--- a/constants/Colors.js
+++ b/constants/Colors.js
@@ -4,6 +4,12 @@ const tintColorRGBA = 'rgba(54,93,134,1)';
const grayLight = '#eeeeee';
const gray = '#cccccc';
const grayDark = '#666666';
+const colorYes = '#2ABE1E';
+const colorNo = '#C70039';
+const colorWait = tintColor;
+const addRemoveIcons = tintColor;
+const addIcons = 'green';
+const removeIcons = 'red';
export default {
primary: tintColor,
@@ -18,6 +24,8 @@ export default {
tabIconDefault: gray,
tabIconSelected: tintColor,
tabBar: '#fefefe',
+ headerTintColor: '#FFFFFF',
+ onPressIcons: '#FFFFFF',
successBackground: 'rgba(229, 229, 229, 0.85)',
sucessText: '#000',
errorBackground: 'rgba(228, 132, 129, 0.85)',
@@ -26,4 +34,15 @@ export default {
warningText: '#ffa0aa',
noticeBackground: tintColor,
noticeText: '#fff',
+ colorYes: '#2ABE1E',
+ colorNo: '#C70039',
+ colorWait: tintColor,
+ addRemoveIcons: tintColor,
+ addIcons: 'green',
+ removeIcons: 'red',
+ button: tintColor,
+ buttonText: '#FFFFFF',
+ dialogButton: '#FFFFFF',
+ buttonDelete: '#d9534f',
+ iconDelete: '#d9534f',
};
diff --git a/languages/ar.json b/languages/ar.json
index ab0deb86..e3e58112 100644
--- a/languages/ar.json
+++ b/languages/ar.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "اكتب تعليقك أو ملاحظتك هنا",
"requiredField": "حقل مطلوب",
"edit": "تغيير",
+ "delete": "حذف",
"cancel": "إلغاء",
"save": "حفظ",
"online": "متصل بالأنترنت",
@@ -25,13 +26,9 @@
"membersActivity": "أفراد",
"moreFields": "المزيد من الحقول",
"nameRequired": "الاسم مطلوب",
- "close": "قريب"
- },
- "appRestart": {
- "message": "سيتم إعادة تشغيل التطبيق لتطبيق التكوين التالي:",
- "button": "حسنا",
- "textDirection": "اتجاه النص",
- "selectedLanguage": "اللغة المختارة"
+ "close": "قريب",
+ "editComment": "تعديل",
+ "deleteComment": "حذف"
},
"loginScreen": {
"domain": {
@@ -71,15 +68,15 @@
"rememberPassword": "تذكر كلمة المرور",
"rememberPasswordActive": "تمكين تسجيل الدخول باستمرار",
"rememberPasswordInactive": "حافظ على تسجيل الدخول معطلة",
- "remove": "إزالة رمز PIN",
- "set": "قم بتعيين رمز PIN",
+ "remove": "إزالة",
+ "set": "جلس",
"pinCode": "كود PIN",
- "enterPin": "أدخل رمز PIN",
+ "enterPin": "أدخل رقم التعريف الشخصي",
"setPin": "قم بتعيين رقم تعريف شخصي جديد",
- "incorrectPin": "رمز PIN غير صحيح",
- "savedPinCode": "تم حفظ رمز PIN بنجاح!",
- "removedPinCode": "تمت إزالة رمز PIN بنجاح!",
- "close": "أغلق"
+ "incorrectPin": "رقم التعريف الشخصي غير صحيح",
+ "savedPinCode": "تم حفظ رمز PIN بنجاح",
+ "removedPinCode": "تمت إزالة رمز PIN بنجاح",
+ "close": "قريب"
},
"contactDetailScreen": {
"addNewContact": "إضافة جهة اتصال جديدة",
@@ -121,6 +118,11 @@
"groupName": {
"label": "أسم المجموعة",
"error": "مطلوب اسم"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "جدول الاجتماع",
+ "quick_button_meeting_postponed": "تم تأجيل الاجتماع",
+ "quick_button_meeting_complete": "اكتمل الاجتماع"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "لا توجد أي مجموعات متاحة حاليًا.",
"noGroupPlacheHolder1": "ربما كانت هناك مشكلة في الحصول عليها من موقعك. اسحب لأسفل لمحاولة التحديث والمحاولة مرة أخرى.",
"noGroupPlacheHolderOffline": "أنت غير متصل حاليًا. تأكد من اتصالك بشبكة wifi أو بيانات الجوال من أجل التحديث والحصول على مجموعاتك."
+ },
+ "appRestart": {
+ "message": "سيتم إعادة تشغيل التطبيق لتطبيق التكوين التالي:",
+ "button": "حسنا",
+ "textDirection": "اتجاه النص",
+ "selectedLanguage": "اللغة المختارة"
}
}
diff --git a/languages/bn.json b/languages/bn.json
index 59d301da..6b838865 100644
--- a/languages/bn.json
+++ b/languages/bn.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "আপনার মন্তব্য বা নোট এখানে লিখুন",
"requiredField": "প্রয়োজনীয় ক্ষেত্র",
"edit": "সম্পাদন করা",
+ "delete": "মুছে ফেলা",
"cancel": "বাতিল",
"save": "সংরক্ষণ করুন",
"online": "অনলাইন",
@@ -25,13 +26,9 @@
"membersActivity": "সদস্য",
"moreFields": "আরও ক্ষেত্র",
"nameRequired": "নাম (প্রয়োজন",
- "close": "ঘনিষ্ঠ"
- },
- "appRestart": {
- "message": "নিম্নলিখিত কনফিগারেশন প্রয়োগ করার জন্য অ্যাপ্লিকেশনটি আবার শুরু হবে:",
- "button": "ঠিক আছে",
- "textDirection": "লেখার দিকবিন্যাস",
- "selectedLanguage": "নির্বাচিত ভাষা"
+ "close": "ঘনিষ্ঠ",
+ "editComment": "সম্পাদনা করুন",
+ "deleteComment": "মুছে ফেলা"
},
"loginScreen": {
"domain": {
@@ -71,15 +68,15 @@
"rememberPassword": "পাসওয়ার্ড মনে",
"rememberPasswordActive": "সক্ষম থাকা লগ ইন করুন",
"rememberPasswordInactive": "লগ ইন অক্ষম রাখুন",
- "remove": "পিন কোড সরান",
- "set": "পিন কোড সেট করুন",
+ "remove": "অপসারণ",
+ "set": "সেট",
"pinCode": "পিনকোড",
- "enterPin": "পিন কোড প্রবেশ করান",
+ "enterPin": "পিন প্রবেশ করান",
"setPin": "নতুন পিন সেট করুন",
- "incorrectPin": "ভুল পিন কোড",
- "savedPinCode": "পিন কোড সফলভাবে সংরক্ষণ করা হয়েছে!",
- "removedPinCode": "পিন কোড সফলভাবে সরানো হয়েছে!",
- "close": "ঘনিষ্ঠ"
+ "incorrectPin": "ভুল পিন",
+ "savedPinCode": "পিন কোড সাফল্যের সাথে সংরক্ষিত হয়েছে",
+ "removedPinCode": "পিন কোড সফলভাবে সরানো হয়েছে",
+ "close": "বন্ধ"
},
"contactDetailScreen": {
"addNewContact": "নতুন পরিচিতি যোগ করুন",
@@ -121,6 +118,11 @@
"groupName": {
"label": "দলের নাম",
"error": "নাম প্রয়োজন"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "সভা নির্ধারিত",
+ "quick_button_meeting_postponed": "সভা স্থগিত",
+ "quick_button_meeting_complete": "সভা সম্পূর্ণ"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "বর্তমানে কোনও গোষ্ঠী উপলব্ধ নেই।",
"noGroupPlacheHolder1": "আপনার সাইট থেকে এগুলি পেতে কোনও সমস্যা হতে পারে। রিফ্রেশ করার চেষ্টা করতে নীচে টানুন এবং আবার চেষ্টা করুন।",
"noGroupPlacheHolderOffline": "আপনি বর্তমানে অফলাইন আপনার গ্রুপগুলি রিফ্রেশ করার জন্য আপনি ওয়াইফাই বা মোবাইল ডেটার সাথে সংযুক্ত আছেন তা নিশ্চিত করুন।"
+ },
+ "appRestart": {
+ "message": "নিম্নলিখিত কনফিগারেশন প্রয়োগ করার জন্য অ্যাপ্লিকেশনটি পুনরায় শুরু হবে:",
+ "button": "ঠিক আছে",
+ "textDirection": "লেখার দিকবিন্যাস",
+ "selectedLanguage": "নির্বাচিত ভাষা"
}
}
diff --git a/languages/en.json b/languages/en.json
index 9e23d671..b90bcd51 100644
--- a/languages/en.json
+++ b/languages/en.json
@@ -16,22 +16,19 @@
"writeYourCommentNoteHere": "Write your comment or note here",
"requiredField": "Required field",
"edit": "Edit",
+ "delete": "Delete",
"cancel": "Cancel",
"save": "Save",
"online": "Online",
- "offline": "offline",
+ "offline": "Offline",
"language": "Language",
"search": "Search",
"membersActivity": "Members",
"moreFields": "More Fields",
"nameRequired": "Name required",
- "close": "Close"
- },
- "appRestart": {
- "message": "The application will be restarted to apply the following configuration:",
- "button": "Ok",
- "textDirection": "Text direction",
- "selectedLanguage": "Selected language"
+ "close": "Close",
+ "editComment": "Edit",
+ "deleteComment": "Delete"
},
"loginScreen": {
"domain": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "Group Name",
"error": "Name is required"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Meeting Scheduled",
+ "quick_button_meeting_postponed": "Meeting Postponed",
+ "quick_button_meeting_complete": "Meeting Complete"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "There are not any groups currently available.",
"noGroupPlacheHolder1": "There may have been a problem getting them from your site. Drag down to try to refresh and try again.",
"noGroupPlacheHolderOffline": "You are currently offline. Ensure you are connected to wifi or mobile data in order to refresh and get your groups."
+ },
+ "appRestart": {
+ "message": "The application will be restarted to apply the following configuration:",
+ "button": "Ok",
+ "textDirection": "Text direction",
+ "selectedLanguage": "Selected language"
}
}
diff --git a/languages/es.json b/languages/es.json
index c8d44ac4..18f9989b 100644
--- a/languages/es.json
+++ b/languages/es.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Escriba su comentario o nota aquí",
"requiredField": "Campo requerido",
"edit": "Editar",
+ "delete": "Eliminar",
"cancel": "Cancelar",
"save": "Guardar",
"online": "En línea",
@@ -25,13 +26,9 @@
"membersActivity": "Miembros",
"moreFields": "Más Campos",
"nameRequired": "Nombre requerido",
- "close": "Cerrar"
- },
- "appRestart": {
- "message": "La aplicación sera reiniciada para aplicar la siguiente configuración:",
- "button": "De acuerdo",
- "textDirection": "Dirección del texto",
- "selectedLanguage": "Lenguaje seleccionado"
+ "close": "Cerrar",
+ "editComment": "Editar",
+ "deleteComment": "Eliminar"
},
"loginScreen": {
"domain": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "Nombre del Grupo",
"error": "El nombre es requerido"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Reunión Programada",
+ "quick_button_meeting_postponed": "Reunión Pospuso",
+ "quick_button_meeting_complete": "Reunión Completa"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "No hay grupos disponibles actualmente.",
"noGroupPlacheHolder1": "Es posible que haya habido un problema para obtenerlos de su sitio. Arrastre hacia abajo para intentar actualizar e intente nuevamente.",
"noGroupPlacheHolderOffline": "Actualmente estás desconectado. Asegúrese de estar conectado a wifi o datos móviles para actualizar y obtener sus grupos."
+ },
+ "appRestart": {
+ "message": "La aplicación sera reiniciada para aplicar la siguiente configuración:",
+ "button": "De acuerdo",
+ "textDirection": "Dirección del texto",
+ "selectedLanguage": "Lenguaje seleccionado"
}
}
diff --git a/languages/fa.json b/languages/fa.json
index 3617ce33..945acc00 100644
--- a/languages/fa.json
+++ b/languages/fa.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "نظر یا یادداشت خود را اینجا بنویسید",
"requiredField": "زمینه مورد نیاز",
"edit": "ویرایش کنید",
+ "delete": "حذف",
"cancel": "لغو",
"save": "صرفه جویی",
"online": "برخط",
@@ -25,13 +26,9 @@
"membersActivity": "اعضا",
"moreFields": "زمینه های بیشتر",
"nameRequired": "نام لازم است",
- "close": "نزدیک"
- },
- "appRestart": {
- "message": "برنامه برای اجرای پیکربندی زیر مجدداً راه اندازی می شود:",
- "button": "خوب",
- "textDirection": "جهت متن",
- "selectedLanguage": "زبان انتخاب شده"
+ "close": "نزدیک",
+ "editComment": "ویرایش کنید",
+ "deleteComment": "حذف"
},
"loginScreen": {
"domain": {
@@ -71,14 +68,14 @@
"rememberPassword": "به یاد داشته باشید کلمه کلیدی",
"rememberPasswordActive": "فعال شوید",
"rememberPasswordInactive": "وارد سیستم غیرفعال شوید",
- "remove": "کد پین را حذف کنید",
- "set": "کد پین را تنظیم کنید",
+ "remove": "برداشتن",
+ "set": "تنظیم",
"pinCode": "کد پین",
- "enterPin": "کد پین را وارد کنید",
- "setPin": "پین جدید را تنظیم کنید",
- "incorrectPin": "کد پین نادرست",
- "savedPinCode": "کد پین با موفقیت ذخیره شد!",
- "removedPinCode": "کد پین با موفقیت حذف شد!",
+ "enterPin": "پین را وارد کنید",
+ "setPin": "تنظیم پین جدید",
+ "incorrectPin": "پین نادرست",
+ "savedPinCode": "کد پین با موفقیت ذخیره شد",
+ "removedPinCode": "کد پین با موفقیت حذف شد",
"close": "نزدیک"
},
"contactDetailScreen": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "اسم گروه",
"error": "نام لازم است"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "جلسه برنامه ریزی شده",
+ "quick_button_meeting_postponed": "جلسه به تعویق افتاد",
+ "quick_button_meeting_complete": "جلسه کامل است"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "در حال حاضر هیچ گروهی موجود نیست",
"noGroupPlacheHolder1": "ممکن است مشکلی در گرفتن آنها از سایت شما وجود داشته باشد. پایین بکشید تا سعی کنید تازه کنید و دوباره امتحان کنید.",
"noGroupPlacheHolderOffline": "شما در حال حاضر آفلاین هستید. برای اطمینان از گروه های خود ، اطمینان حاصل کنید که به داده های wifi یا تلفن همراه وصل شده اید."
+ },
+ "appRestart": {
+ "message": "برنامه برای اجرای پیکربندی زیر مجدداً راه اندازی می شود:",
+ "button": "خوب",
+ "textDirection": "جهت متن",
+ "selectedLanguage": "زبان انتخاب شده"
}
}
diff --git a/languages/fr.json b/languages/fr.json
index efe66ea0..d1cc4036 100644
--- a/languages/fr.json
+++ b/languages/fr.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Écrivez votre commentaire ou note ici",
"requiredField": "champs requis",
"edit": "modifier",
+ "delete": "Supprimer",
"cancel": "Annuler",
"save": "sauver",
"online": "En ligne",
@@ -25,13 +26,9 @@
"membersActivity": "Membres",
"moreFields": "Plus de champs",
"nameRequired": "Nom obligatoire",
- "close": "proche"
- },
- "appRestart": {
- "message": "L'application sera redémarrée pour appliquer la configuration suivante:",
- "button": "D'accord",
- "textDirection": "Direction du texte",
- "selectedLanguage": "Langue choisie"
+ "close": "proche",
+ "editComment": "Éditer",
+ "deleteComment": "Supprimer"
},
"loginScreen": {
"domain": {
@@ -71,14 +68,14 @@
"rememberPassword": "se souvenir du mot de passe",
"rememberPasswordActive": "Rester connecté activé",
"rememberPasswordInactive": "Rester connecté désactivé",
- "remove": "Supprimer le code PIN",
- "set": "Définir le code PIN",
+ "remove": "Retirer",
+ "set": "Ensemble",
"pinCode": "Code PIN",
"enterPin": "Entrez le code PIN",
"setPin": "Définir un nouveau code PIN",
- "incorrectPin": "Code PIN incorrect",
- "savedPinCode": "Le code PIN a été enregistré avec succès!",
- "removedPinCode": "Le code PIN a été supprimé avec succès!",
+ "incorrectPin": "PIN incorrect",
+ "savedPinCode": "Code PIN enregistré avec succès",
+ "removedPinCode": "Code PIN supprimé avec succès",
"close": "Fermer"
},
"contactDetailScreen": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "Nom de groupe",
"error": "Nom obligatoire"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Réunion programmée",
+ "quick_button_meeting_postponed": "Réunion reportée",
+ "quick_button_meeting_complete": "Réunion terminée"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "Aucun groupe n'est actuellement disponible.",
"noGroupPlacheHolder1": "Il peut y avoir eu un problème pour les obtenir à partir de votre site. Faites glisser vers le bas pour essayer de rafraîchir et réessayez.",
"noGroupPlacheHolderOffline": "Vous êtes actuellement hors ligne. Assurez-vous que vous êtes connecté au wifi ou aux données mobiles afin de rafraîchir et d'obtenir vos groupes."
+ },
+ "appRestart": {
+ "message": "L'application sera redémarrée pour appliquer la configuration suivante:",
+ "button": "D'accord",
+ "textDirection": "Direction du texte",
+ "selectedLanguage": "Langue sélectionnée"
}
}
diff --git a/languages/hr.json b/languages/hr.json
new file mode 100644
index 00000000..754ad822
--- /dev/null
+++ b/languages/hr.json
@@ -0,0 +1,149 @@
+{
+ "global": {
+ "error": {
+ "code": "Kodirati: ",
+ "message": "Poruka: "
+ },
+ "success": {
+ "save": "Podaci su uspješno spremljeni!"
+ },
+ "groups": "Grupe",
+ "details": "Pojedinosti",
+ "selectPeopleGroups": "Odaberite Grupe ljudi",
+ "address": "Adresa",
+ "progress": "Napredak",
+ "commentsActivity": "Komentari i aktivnosti",
+ "writeYourCommentNoteHere": "Ovdje napišite svoj komentar ili bilješku",
+ "requiredField": "Obavezno polje",
+ "edit": "Uredi",
+ "delete": "Izbrisati",
+ "cancel": "Otkazati",
+ "save": "Uštedjeti",
+ "online": "Na liniji",
+ "offline": "offline",
+ "language": "Jezik",
+ "search": "traži",
+ "membersActivity": "Članovi",
+ "moreFields": "Još polja",
+ "nameRequired": "Ime (obavezno",
+ "close": "Zatvoriti",
+ "editComment": "Uredi",
+ "deleteComment": "Izbrisati"
+ },
+ "loginScreen": {
+ "domain": {
+ "label": "URL",
+ "placeholder": "Npr. myteam.mydomain.com",
+ "error": "Domena je obavezna",
+ "errorForgotPass": "Unesite URL da biste započeli s preuzimanjem lozinke"
+ },
+ "username": {
+ "label": "Korisničko ime",
+ "error": "Korisničko ime je obavezno"
+ },
+ "password": {
+ "label": "Zaporka",
+ "error": "potrebna je lozinka"
+ },
+ "logIn": "Prijaviti se",
+ "forgotPassword": "Izgubili ste lozinku?",
+ "errors": {
+ "invalidUsername": "Nepoznato korisničko ime. Provjerite ponovo ili isprobajte svoju adresu e-pošte.",
+ "incorrectPassword": "Lozinka koju ste unijeli za korisničko ime je netočna"
+ }
+ },
+ "contactsScreen": {
+ "contacts": "Kontakti",
+ "noContactPlacheHolder": "Trenutno nema dostupnih kontakata.",
+ "noContactPlacheHolder1": "Možda je došlo do problema pri preuzimanju s vaše web lokacije. Povucite prema dolje da biste se pokušali osvježiti i pokušajte ponovo.",
+ "noContactPlacheHolderOffline": "Trenutno ste offline. Provjerite jeste li povezani na WiFi ili mobilne podatke kako biste osvježili i dobili svoje kontakte."
+ },
+ "settingsScreen": {
+ "settings": "Postavke",
+ "networkUnavailable": "Mreža nije dostupna. Sada u OFFLINE načinu",
+ "networkAvailable": "Otkrivena mreža. Povratak u ONLINE način",
+ "storybook": "Knjiga pripovjedaka",
+ "logout": "Odjavi se",
+ "helpSupport": "Pomoć / podrška",
+ "rememberPassword": "Zapamti lozinku",
+ "rememberPasswordActive": "Neka prijava bude omogućena",
+ "rememberPasswordInactive": "Ostanite prijavljeni onemogućeni",
+ "remove": "Ukloniti",
+ "set": "Postavi",
+ "pinCode": "PIN kod",
+ "enterPin": "Unesite PIN",
+ "setPin": "Postavite novi PIN",
+ "incorrectPin": "Neispravan PIN",
+ "savedPinCode": "PIN kod je uspješno spremljen",
+ "removedPinCode": "PIN kod je uspješno uklonjen",
+ "close": "Zatvoriti"
+ },
+ "contactDetailScreen": {
+ "addNewContact": "Dodaj novi kontakt",
+ "subAssignThisContact": "Pododijelite ovaj kontakt",
+ "mobile": "Telefon",
+ "selectLocations": "Odaberite Lokacije",
+ "selectSources": "Odaberite izvore",
+ "connections": "Veze",
+ "addGroup": "Dodaj grupu",
+ "addConnection": "Dodaj vezu",
+ "addBaptizedBy": "Dodaj krštenik",
+ "addBaptized": "Dodaj kršteno",
+ "addCoachedBy": "Dodaj trenirao",
+ "addCoaching": "Dodajte treniranje",
+ "phoneNumber": "Broj telefona",
+ "initialComment": "Početni komentar",
+ "socialMedia": "Društveni mediji",
+ "noContactCommentPlacheHolder": "Trenutno nema dostupnih komentara na kontakt.",
+ "fullName": {
+ "label": "Puno ime",
+ "error": "Ime je obavezno"
+ },
+ "noContactCommentPlacheHolder1": "Možda je došlo do problema pri preuzimanju s vaše web lokacije. Povucite prema dolje da biste se pokušali osvježiti i pokušajte ponovo.",
+ "noContactCommentPlacheHolderOffline": "Trenutno ste offline. Provjerite jeste li povezani na WiFi ili mobilne podatke kako biste osvježili i dobili komentar na kontakt."
+ },
+ "groupDetailScreen": {
+ "addNewGroup": "Dodaj novu grupu",
+ "selectCoaches": "Odaberite Grupni trener",
+ "searchGroups": "Pretražite grupe",
+ "searchPeerGroups": "Pretražite grupe vršnjaka",
+ "childGroup": "Dječja grupa",
+ "searchChildGroups": "Pretražite dječje skupine",
+ "addMember": "Dodaj člana",
+ "noGroupCommentPlacheHolder": "Trenutno nema dostupnih komentara grupe.",
+ "noGroupCommentPlacheHolder1": "Možda je došlo do problema pri preuzimanju s vaše web lokacije. Povucite prema dolje da biste se pokušali osvježiti i pokušajte ponovo.",
+ "noGroupCommentPlacheHolderOffline": "Trenutno ste offline. Provjerite jeste li povezani na WiFi ili mobilne podatke kako biste osvježili i dobili komentar svoje grupe.",
+ "selectLocations": "Odaberite Lokacije",
+ "noMembersMessage": "Nema članova. Dodirnite ovdje ili na Uredi da biste dodali neke članove u ovu grupu.",
+ "groupName": {
+ "label": "Grupno ime",
+ "error": "Ime je obavezno"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Sastanak zakazan",
+ "quick_button_meeting_postponed": "Sastanak odgođen",
+ "quick_button_meeting_complete": "Sastanak završen"
+ }
+ },
+ "notificationsScreen": {
+ "notifications": "Obavijesti",
+ "loadMore": "Učitaj više",
+ "new": "Novi",
+ "unRead": "Nepročitano",
+ "all": "svi",
+ "markAll": "Označi sve",
+ "dontHaveNotificationsUnread": "Nema nepročitanih obavijesti",
+ "dontHaveNotifications": "Nema obavijesti"
+ },
+ "groupsScreen": {
+ "noGroupPlacheHolder": "Trenutno nema dostupnih grupa.",
+ "noGroupPlacheHolder1": "Možda je došlo do problema pri preuzimanju s vaše web lokacije. Povucite prema dolje da biste se pokušali osvježiti i pokušajte ponovo.",
+ "noGroupPlacheHolderOffline": "Trenutno ste offline. Provjerite jeste li povezani na WiFi ili mobilne podatke kako biste osvježili i prikupili svoje grupe."
+ },
+ "appRestart": {
+ "message": "Program će se ponovo pokrenuti kako bi primijenio sljedeću konfiguraciju:",
+ "button": "U redu",
+ "textDirection": "Smjer teksta",
+ "selectedLanguage": "Odabrani jezik"
+ }
+}
diff --git a/languages/hr.test.js b/languages/hr.test.js
new file mode 100644
index 00000000..2ab4a839
--- /dev/null
+++ b/languages/hr.test.js
@@ -0,0 +1,14 @@
+import i18n from '.';
+const locale = 'hr';
+
+describe('languages/' + locale, () => {
+ beforeAll(() => i18n.setLocale(locale, false));
+
+ test('test missing translation', () => {
+ expect(i18n.t('global.zz')).toEqual('[missing "' + locale + '.global.zz" translation]');
+ });
+
+ test('test global.success.save translation', () => {
+ expect(i18n.t('global.success.save')).toEqual('Podaci su uspješno spremljeni!');
+ });
+});
diff --git a/languages/id.json b/languages/id.json
index 77db7615..cc5e0fce 100644
--- a/languages/id.json
+++ b/languages/id.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Tulis komentar atau komentar Anda di sini",
"requiredField": "kolom yang harus diisi",
"edit": "Edit",
+ "delete": "Menghapus",
"cancel": "Membatalkan",
"save": "Menyimpan",
"online": "On line",
@@ -25,13 +26,9 @@
"membersActivity": "Anggota",
"moreFields": "Lebih banyak bidang",
"nameRequired": "Nama (wajib",
- "close": "Menutup"
- },
- "appRestart": {
- "message": "Aplikasi akan dihidupkan ulang untuk menerapkan konfigurasi berikut:",
- "button": "baik",
- "textDirection": "Arah teks",
- "selectedLanguage": "Bahasa yang dipilih"
+ "close": "Menutup",
+ "editComment": "Edit",
+ "deleteComment": "Menghapus"
},
"loginScreen": {
"domain": {
@@ -71,14 +68,14 @@
"rememberPassword": "ingat kata Sandi",
"rememberPasswordActive": "Tetap masuk log diaktifkan",
"rememberPasswordInactive": "Tetap masuk log dinonaktifkan",
- "remove": "Hapus kode PIN",
- "set": "Setel kode PIN",
+ "remove": "Menghapus",
+ "set": "Set",
"pinCode": "Kode PIN",
- "enterPin": "Masukkan kode PIN",
- "setPin": "Tetapkan PIN baru",
- "incorrectPin": "Kode PIN salah",
- "savedPinCode": "Kode PIN berhasil disimpan!",
- "removedPinCode": "Kode PIN berhasil dihapus!",
+ "enterPin": "Masukkan PIN",
+ "setPin": "Setel PIN baru",
+ "incorrectPin": "PIN salah",
+ "savedPinCode": "Kode PIN berhasil disimpan",
+ "removedPinCode": "Kode PIN berhasil dihapus",
"close": "Menutup"
},
"contactDetailScreen": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "Nama grup",
"error": "Nama harus diisi"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Rapat Terjadwal",
+ "quick_button_meeting_postponed": "Rapat Ditunda",
+ "quick_button_meeting_complete": "Rapat Selesai"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "Tidak ada grup yang tersedia saat ini.",
"noGroupPlacheHolder1": "Mungkin ada masalah saat mendapatkannya dari situs Anda. Seret ke bawah untuk mencoba menyegarkan dan coba lagi.",
"noGroupPlacheHolderOffline": "Anda sedang offline. Pastikan Anda terhubung ke wifi atau data seluler untuk menyegarkan dan mendapatkan grup Anda."
+ },
+ "appRestart": {
+ "message": "Aplikasi akan dimulai ulang untuk menerapkan konfigurasi berikut:",
+ "button": "Baik",
+ "textDirection": "Arah teks",
+ "selectedLanguage": "Bahasa yang dipilih"
}
}
diff --git a/languages/index.js b/languages/index.js
index 7f321548..1c733a58 100644
--- a/languages/index.js
+++ b/languages/index.js
@@ -12,6 +12,9 @@ import * as id from './id.json';
import * as nl from './nl.json';
import * as ptBR from './pt.json';
import * as ru from './ru.json';
+import * as sr from './sr.json';
+import * as sl from './sl.json';
+import * as hr from './hr.json';
import * as sw from './sw.json';
import * as tr from './tr.json';
import * as zhCn from './zhCn.json';
@@ -32,6 +35,9 @@ i18n.translations = {
'nl-NL': nl,
'pt-BR': ptBR,
'ru-RU': ru,
+ sr,
+ sl,
+ hr,
sw,
'tr-TR': tr,
'zh-CN': zhCn,
diff --git a/languages/locales.js b/languages/locales.js
index 64b60282..19e57c52 100644
--- a/languages/locales.js
+++ b/languages/locales.js
@@ -41,12 +41,27 @@ export default [
},
{
code: 'pt-BR',
- name: 'Português',
+ name: 'Português do Brasil',
rtl: false,
},
{
code: 'ru-RU',
- name: 'русский язык',
+ name: 'русский',
+ rtl: false,
+ },
+ {
+ code: 'sr',
+ name: 'српски',
+ rtl: false,
+ },
+ {
+ code: 'sl',
+ name: 'slovenščina',
+ rtl: false,
+ },
+ {
+ code: 'hr',
+ name: 'hrvatski',
rtl: false,
},
{
diff --git a/languages/moment.js b/languages/moment.js
index 055a0020..c5403013 100644
--- a/languages/moment.js
+++ b/languages/moment.js
@@ -10,6 +10,9 @@ require('moment/locale/id');
require('moment/locale/nl');
require('moment/locale/pt');
require('moment/locale/ru');
+require('moment/locale/sr');
+require('moment/locale/sl');
+require('moment/locale/hr');
require('moment/locale/sw');
require('moment/locale/tr');
require('moment/locale/zh-cn');
diff --git a/languages/nl.json b/languages/nl.json
index 79dc6811..e00169cd 100644
--- a/languages/nl.json
+++ b/languages/nl.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Schrijf hier je reactie of opmerking",
"requiredField": "verplicht veld",
"edit": "Bewerk",
+ "delete": "Verwijderen",
"cancel": "annuleren",
"save": "Opslaan",
"online": "Online",
@@ -25,13 +26,9 @@
"membersActivity": "leden",
"moreFields": "Meer velden",
"nameRequired": "Naam (vereist",
- "close": "Dichtbij"
- },
- "appRestart": {
- "message": "De applicatie wordt opnieuw opgestart om de volgende configuratie toe te passen:",
- "button": "OK",
- "textDirection": "Tekstrichting",
- "selectedLanguage": "Geselecteerde taal"
+ "close": "Dichtbij",
+ "editComment": "Bewerk",
+ "deleteComment": "Verwijderen"
},
"loginScreen": {
"domain": {
@@ -71,15 +68,15 @@
"rememberPassword": "Onthoud wachtwoord",
"rememberPasswordActive": "Blijf ingelogd ingeschakeld",
"rememberPasswordInactive": "Blijf ingelogd uitgeschakeld",
- "remove": "PIN-code verwijderen",
- "set": "Pincode instellen",
+ "remove": "Verwijderen",
+ "set": "Set",
"pinCode": "Pincode",
- "enterPin": "Voer pincode in",
- "setPin": "Nieuwe pincode instellen",
+ "enterPin": "Voer Pin-code in",
+ "setPin": "Stel een nieuwe pincode in",
"incorrectPin": "Onjuiste pincode",
- "savedPinCode": "PIN-code succesvol opgeslagen!",
- "removedPinCode": "PIN-code succesvol verwijderd!",
- "close": "dichtbij"
+ "savedPinCode": "PIN-code succesvol opgeslagen",
+ "removedPinCode": "PIN-code succesvol verwijderd",
+ "close": "Dichtbij"
},
"contactDetailScreen": {
"addNewContact": "Voeg nieuw contact toe",
@@ -121,6 +118,11 @@
"groupName": {
"label": "Groepsnaam",
"error": "Naam is vereist"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Vergadering gepland",
+ "quick_button_meeting_postponed": "Vergadering uitgesteld",
+ "quick_button_meeting_complete": "Vergadering voltooid"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "Er zijn momenteel geen groepen beschikbaar.",
"noGroupPlacheHolder1": "Er is mogelijk een probleem opgetreden bij het ophalen van uw site. Sleep omlaag om te proberen te vernieuwen en probeer het opnieuw.",
"noGroupPlacheHolderOffline": "U bent momenteel offline. Zorg ervoor dat u bent verbonden met wifi of mobiele gegevens om uw groepen te vernieuwen en op te halen."
+ },
+ "appRestart": {
+ "message": "De applicatie wordt opnieuw gestart om de volgende configuratie toe te passen:",
+ "button": "OK",
+ "textDirection": "Tekstrichting",
+ "selectedLanguage": "Geselecteerde taal"
}
}
diff --git a/languages/pt.json b/languages/pt.json
index 6dc1d167..5f3c09e4 100644
--- a/languages/pt.json
+++ b/languages/pt.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Escreva seu comentário ou anotação aqui",
"requiredField": "Campo obrigatório",
"edit": "editar",
+ "delete": "Excluir",
"cancel": "Cancelar",
"save": "Salvar",
"online": "online",
@@ -25,13 +26,9 @@
"membersActivity": "Membros",
"moreFields": "Mais campos",
"nameRequired": "Nome necessário",
- "close": "Fechar"
- },
- "appRestart": {
- "message": "O aplicativo será reiniciado para aplicar a seguinte configuração:",
- "button": "Está bem",
- "textDirection": "Direção do texto",
- "selectedLanguage": "Idioma selecionado"
+ "close": "Fechar",
+ "editComment": "Editar",
+ "deleteComment": "Excluir"
},
"loginScreen": {
"domain": {
@@ -71,15 +68,15 @@
"rememberPassword": "Lembrar senha",
"rememberPasswordActive": "Manter-se logado está ligado",
"rememberPasswordInactive": "Manter-se logado está desligado",
- "remove": "Remover código PIN",
- "set": "Definir código PIN",
+ "remove": "Remover",
+ "set": "Conjunto",
"pinCode": "Código PIN",
- "enterPin": "Digite o código PIN",
+ "enterPin": "Entrar no pino",
"setPin": "Definir novo PIN",
- "incorrectPin": "Código PIN incorreto",
- "savedPinCode": "Código PIN salvo com sucesso!",
- "removedPinCode": "Código PIN removido com sucesso!",
- "close": "Fechar"
+ "incorrectPin": "PIN incorreto",
+ "savedPinCode": "Código PIN salvo com sucesso",
+ "removedPinCode": "Código PIN removido com sucesso",
+ "close": "Perto"
},
"contactDetailScreen": {
"addNewContact": "Adicionar novo contato",
@@ -121,6 +118,11 @@
"groupName": {
"label": "Nome do Grupo",
"error": "Nome é necessário"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Reunião agendada",
+ "quick_button_meeting_postponed": "Reunião adiada",
+ "quick_button_meeting_complete": "Reunião Completa"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "Não há grupos disponíveis no momento",
"noGroupPlacheHolder1": "Pode haver um problema ao removê-los do seu local. Arraste-os para tentar atualizar e tente novamente. ",
"noGroupPlacheHolderOffline": "Você está offline. Certifique-se de que está conectado à rede Wifi ou dados móveis para atualizar e obter seus grupos."
+ },
+ "appRestart": {
+ "message": "O aplicativo será reiniciado para aplicar a seguinte configuração:",
+ "button": "Está bem",
+ "textDirection": "Direção do texto",
+ "selectedLanguage": "Idioma selecionado"
}
}
diff --git a/languages/ru.json b/languages/ru.json
index 7e4d2a7e..db6cbcec 100644
--- a/languages/ru.json
+++ b/languages/ru.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Напишите свой комментарий или заметку здесь",
"requiredField": "Обязательное поле",
"edit": "Редактировать",
+ "delete": "Удалить",
"cancel": "Отмена",
"save": "Сохранить",
"online": "Онлайн",
@@ -25,13 +26,9 @@
"membersActivity": "Члены",
"moreFields": "Больше полей",
"nameRequired": "Имя обязательно",
- "close": "близко"
- },
- "appRestart": {
- "message": "Приложение будет перезапущено для применения следующей конфигурации:",
- "button": "Хорошо",
- "textDirection": "Направление текста",
- "selectedLanguage": "Выбранный язык"
+ "close": "близко",
+ "editComment": "редактировать",
+ "deleteComment": "Удалить"
},
"loginScreen": {
"domain": {
@@ -71,14 +68,14 @@
"rememberPassword": "Запомнить пароль",
"rememberPasswordActive": "Режим \"Оставаться в системе\" включен",
"rememberPasswordInactive": "Режим \"Оставаться в системе\" выключен",
- "remove": "Удалить ПИН код",
- "set": "Установить PIN-код",
+ "remove": "удалять",
+ "set": "Устанавливать",
"pinCode": "Пин-код",
- "enterPin": "Введите пин код",
+ "enterPin": "Введите PIN-код",
"setPin": "Установить новый PIN-код",
"incorrectPin": "Неверный PIN-код",
- "savedPinCode": "ПИН-код успешно сохранен!",
- "removedPinCode": "PIN-код успешно удален!",
+ "savedPinCode": "PIN-код успешно сохранен",
+ "removedPinCode": "PIN-код успешно удален",
"close": "близко"
},
"contactDetailScreen": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "Имя группы",
"error": "Имя обязательно"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Встреча запланирована",
+ "quick_button_meeting_postponed": "Встреча отложена",
+ "quick_button_meeting_complete": "Встреча завершена"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "В настоящее время нет доступных групп.",
"noGroupPlacheHolder1": "Возможно, возникла проблема при получении их с вашего сайта. Попытайтесь еще раз (обновите экран, потянув его вниз).",
"noGroupPlacheHolderOffline": "Вы в настоящее время не в сети. Убедитесь, что вы подключены к Wi-Fi или мобильным данным, чтобы обновить и получить ваши группы."
+ },
+ "appRestart": {
+ "message": "Приложение будет перезапущено для применения следующей конфигурации:",
+ "button": "Хорошо",
+ "textDirection": "Направление текста",
+ "selectedLanguage": "Выбранный язык"
}
}
diff --git a/languages/sl.json b/languages/sl.json
new file mode 100644
index 00000000..4fc1c6a3
--- /dev/null
+++ b/languages/sl.json
@@ -0,0 +1,149 @@
+{
+ "global": {
+ "error": {
+ "code": "Koda: ",
+ "message": "Sporočilo: "
+ },
+ "success": {
+ "save": "Podatki so bili uspešno shranjeni!"
+ },
+ "groups": "Skupine",
+ "details": "Podrobnosti",
+ "selectPeopleGroups": "Izberite Skupine ljudi",
+ "address": "Naslov",
+ "progress": "Napredek",
+ "commentsActivity": "Pripombe in dejavnost",
+ "writeYourCommentNoteHere": "Tu napišite svoj komentar ali opombo",
+ "requiredField": "Zahtevano polje",
+ "edit": "Uredi",
+ "delete": "Izbriši",
+ "cancel": "Prekliči",
+ "save": "Shrani",
+ "online": "Na spletu",
+ "offline": "brez povezave",
+ "language": "Jezik",
+ "search": "Iskanje",
+ "membersActivity": "Člani",
+ "moreFields": "Več polj",
+ "nameRequired": "Ime je potrebno",
+ "close": "Zapri",
+ "editComment": "Uredi",
+ "deleteComment": "Izbriši"
+ },
+ "loginScreen": {
+ "domain": {
+ "label": "URL",
+ "placeholder": "Npr. myteam.mydomain.com",
+ "error": "Domena je obvezna",
+ "errorForgotPass": "Vnesite URL za začetek pridobivanja gesla"
+ },
+ "username": {
+ "label": "Uporabniško ime",
+ "error": "Uporabniško ime je potrebno"
+ },
+ "password": {
+ "label": "Geslo",
+ "error": "zahtevano je geslo"
+ },
+ "logIn": "Vpiši se",
+ "forgotPassword": "Pozabili geslo?",
+ "errors": {
+ "invalidUsername": "Neznano uporabniško ime. Ponovno preverite ali poskusite svoj e-poštni naslov.",
+ "incorrectPassword": "Geslo, ki ste ga vnesli za uporabniško ime, ni pravilno"
+ }
+ },
+ "contactsScreen": {
+ "contacts": "Stiki",
+ "noContactPlacheHolder": "Trenutno ni na voljo nobenega stika.",
+ "noContactPlacheHolder1": "Morda je prišlo do težave pri pridobivanju le-teh z vašega spletnega mesta. Povlecite navzdol, da se poskusite osvežiti in poskusite znova.",
+ "noContactPlacheHolderOffline": "Trenutno ste brez povezave. Zagotovite, da ste povezani z wifi ali mobilnimi podatki, da osvežite in dobite stike."
+ },
+ "settingsScreen": {
+ "settings": "Nastavitve",
+ "networkUnavailable": "Omrežje ni na voljo. Zdaj v načinu OFFLINE",
+ "networkAvailable": "Zaznano je omrežje. Nazaj v ONLINE način",
+ "storybook": "Zbirka zgodb",
+ "logout": "Odjava",
+ "helpSupport": "Pomoč / podpora",
+ "rememberPassword": "Zapomni si geslo",
+ "rememberPasswordActive": "Naj bo prijava omogočena",
+ "rememberPasswordInactive": "Prijavi se onemogočeno",
+ "remove": "Odstrani",
+ "set": "Nastavite",
+ "pinCode": "PIN koda",
+ "enterPin": "Vnesite PIN",
+ "setPin": "Nastavite novo kodo PIN",
+ "incorrectPin": "Napačna koda PIN",
+ "savedPinCode": "Koda PIN je bila uspešno shranjena",
+ "removedPinCode": "Koda PIN je bila uspešno odstranjena",
+ "close": "Zapri"
+ },
+ "contactDetailScreen": {
+ "addNewContact": "Dodaj nov stik",
+ "subAssignThisContact": "Pododelite ta stik",
+ "mobile": "Mobilni",
+ "selectLocations": "Izberite Lokacije",
+ "selectSources": "Izberite vire",
+ "connections": "Povezave",
+ "addGroup": "Dodaj skupino",
+ "addConnection": "Dodaj povezavo",
+ "addBaptizedBy": "Dodaj krščen z",
+ "addBaptized": "Dodajte krst",
+ "addCoachedBy": "Dodaj trener",
+ "addCoaching": "Dodaj trenerje",
+ "phoneNumber": "Telefonska številka",
+ "initialComment": "Začetni komentar",
+ "socialMedia": "Socialni mediji",
+ "noContactCommentPlacheHolder": "Trenutno ni na voljo nobenih komentarjev za stike.",
+ "fullName": {
+ "label": "Polno ime",
+ "error": "Ime je obvezno"
+ },
+ "noContactCommentPlacheHolder1": "Morda je prišlo do težave pri pridobivanju le-teh z vašega spletnega mesta. Povlecite navzdol, da se poskusite osvežiti in poskusite znova.",
+ "noContactCommentPlacheHolderOffline": "Trenutno ste brez povezave. Zagotovite, da ste povezani z wifi ali mobilnimi podatki, da osvežite in dobite komentar."
+ },
+ "groupDetailScreen": {
+ "addNewGroup": "Dodaj novo skupino",
+ "selectCoaches": "Izberite Coach Coach",
+ "searchGroups": "Iskanje skupin",
+ "searchPeerGroups": "Iščite skupine vrstnikov",
+ "childGroup": "Otroška skupina",
+ "searchChildGroups": "Poiščite otroške skupine",
+ "addMember": "Dodaj člana",
+ "noGroupCommentPlacheHolder": "Trenutno ni na voljo nobenih komentarjev skupin.",
+ "noGroupCommentPlacheHolder1": "Morda je prišlo do težave pri pridobivanju le-teh z vašega spletnega mesta. Povlecite navzdol, da se poskusite osvežiti in poskusite znova.",
+ "noGroupCommentPlacheHolderOffline": "Trenutno ste brez povezave. Zagotovite, da ste povezani z wifi ali mobilnimi podatki, da osvežite in dobite komentar svoje skupine.",
+ "selectLocations": "Izberite Lokacije",
+ "noMembersMessage": "Ni članov",
+ "groupName": {
+ "label": "Ime skupine",
+ "error": "Ime je obvezno"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Načrtovan sestanek",
+ "quick_button_meeting_postponed": "Seja prestavljena",
+ "quick_button_meeting_complete": "Sestanek končan"
+ }
+ },
+ "notificationsScreen": {
+ "notifications": "Obvestila",
+ "loadMore": "Naloži več",
+ "new": "Novo",
+ "unRead": "Neprebrano",
+ "all": "Vse",
+ "markAll": "Označi vse",
+ "dontHaveNotificationsUnread": "Brez prebranih obvestil",
+ "dontHaveNotifications": "Brez obvestil"
+ },
+ "groupsScreen": {
+ "noGroupPlacheHolder": "Trenutno ni na voljo nobene skupine.",
+ "noGroupPlacheHolder1": "Morda je prišlo do težave pri pridobivanju le-teh z vašega spletnega mesta. Povlecite navzdol, da se poskusite osvežiti in poskusite znova.",
+ "noGroupPlacheHolderOffline": "Trenutno ste brez povezave. Zagotovite, da ste povezani z wifi ali mobilnimi podatki, da osvežite in dobite svoje skupine."
+ },
+ "appRestart": {
+ "message": "Aplikacija se bo znova zagnala, da bo uporabila naslednjo konfiguracijo:",
+ "button": "V redu",
+ "textDirection": "Smer besedila",
+ "selectedLanguage": "Izbrani jezik"
+ }
+}
diff --git a/languages/sl.test.js b/languages/sl.test.js
new file mode 100644
index 00000000..6bd4ee7a
--- /dev/null
+++ b/languages/sl.test.js
@@ -0,0 +1,14 @@
+import i18n from '.';
+const locale = 'sl';
+
+describe('languages/' + locale, () => {
+ beforeAll(() => i18n.setLocale(locale, false));
+
+ test('test missing translation', () => {
+ expect(i18n.t('global.zz')).toEqual('[missing "' + locale + '.global.zz" translation]');
+ });
+
+ test('test global.success.save translation', () => {
+ expect(i18n.t('global.success.save')).toEqual('Podatki so bili uspešno shranjeni!');
+ });
+});
diff --git a/languages/sr.json b/languages/sr.json
new file mode 100644
index 00000000..5c8ba7b4
--- /dev/null
+++ b/languages/sr.json
@@ -0,0 +1,149 @@
+{
+ "global": {
+ "error": {
+ "code": "Шифра: ",
+ "message": "Порука: "
+ },
+ "success": {
+ "save": "Подаци су успешно сачувани!"
+ },
+ "groups": "Групе",
+ "details": "Детаљи",
+ "selectPeopleGroups": "Изаберите Групе људи",
+ "address": "Адреса",
+ "progress": "Напредак",
+ "commentsActivity": "Коментари и активност",
+ "writeYourCommentNoteHere": "Напишите свој коментар или белешку овде",
+ "requiredField": "Обавезно поље",
+ "edit": "Уредити",
+ "delete": "Избриши",
+ "cancel": "Поништити, отказати",
+ "save": "сачувати",
+ "online": "Онлине",
+ "offline": "одсутан",
+ "language": "Језик",
+ "search": "Претрага",
+ "membersActivity": "Чланови",
+ "moreFields": "Још поља",
+ "nameRequired": "Име (обавезно",
+ "close": "Близу",
+ "editComment": "Уредити",
+ "deleteComment": "Избриши"
+ },
+ "loginScreen": {
+ "domain": {
+ "label": "УРЛ",
+ "placeholder": "На пример. митеам.мидомаин.цом",
+ "error": "Домен је обавезан",
+ "errorForgotPass": "Унесите УРЛ да бисте започели преузимање лозинке"
+ },
+ "username": {
+ "label": "Корисничко име",
+ "error": "Корисничко име је обавезно"
+ },
+ "password": {
+ "label": "Лозинка",
+ "error": "Потребна је шифра"
+ },
+ "logIn": "Пријавите се",
+ "forgotPassword": "Заборавили сте лозинку?",
+ "errors": {
+ "invalidUsername": "Непознато корисничко име. Проверите поново или испробајте своју адресу е-поште.",
+ "incorrectPassword": "Лозинка коју сте унели за корисничко име је нетачна"
+ }
+ },
+ "contactsScreen": {
+ "contacts": "Контакти",
+ "noContactPlacheHolder": "Тренутно нема доступних контаката.",
+ "noContactPlacheHolder1": "Можда је дошло до проблема при преузимању са ваше веб локације. Превуците надоле да бисте покушали да освежите и покушајте поново.",
+ "noContactPlacheHolderOffline": "Тренутно сте ван мреже. Уверите се да сте повезани на ВиФи или мобилне податке како бисте освежили и добили своје контакте."
+ },
+ "settingsScreen": {
+ "settings": "Подешавања",
+ "networkUnavailable": "Мрежа није доступна. Сада у ОФФЛИНЕ режиму",
+ "networkAvailable": "Мрежа је откривена. Повратак у ОНЛИНЕ режим",
+ "storybook": "Књига прича",
+ "logout": "Одјава",
+ "helpSupport": "Помоћ / подршка",
+ "rememberPassword": "Запамти лозинку",
+ "rememberPasswordActive": "Останите пријављени",
+ "rememberPasswordInactive": "Останите пријављени онемогућени",
+ "remove": "Уклоните",
+ "set": "Комплет",
+ "pinCode": "Пин код",
+ "enterPin": "Унесите ПИН",
+ "setPin": "Подесите нови ПИН",
+ "incorrectPin": "Нетачан ПИН",
+ "savedPinCode": "ПИН код је успешно сачуван",
+ "removedPinCode": "ПИН код је успешно уклоњен",
+ "close": "Близу"
+ },
+ "contactDetailScreen": {
+ "addNewContact": "Додај нови контакт",
+ "subAssignThisContact": "Пододелите овај контакт",
+ "mobile": "Телефон",
+ "selectLocations": "Изаберите Лоцатионс",
+ "selectSources": "Изаберите изворе",
+ "connections": "Везе",
+ "addGroup": "Додај групу",
+ "addConnection": "Додај везу",
+ "addBaptizedBy": "Додај крштених од",
+ "addBaptized": "Додати крштено",
+ "addCoachedBy": "Додај тренирао",
+ "addCoaching": "Додајте тренирање",
+ "phoneNumber": "Број телефона",
+ "initialComment": "Почетни коментар",
+ "socialMedia": "Друштвени медији",
+ "noContactCommentPlacheHolder": "Тренутно нема доступних коментара на контакт.",
+ "fullName": {
+ "label": "Пуно име",
+ "error": "Име је обавезно"
+ },
+ "noContactCommentPlacheHolder1": "Можда је дошло до проблема при преузимању са ваше веб локације. Превуците надоле да бисте покушали да освежите и покушајте поново.",
+ "noContactCommentPlacheHolderOffline": "Тренутно сте ван мреже. Уверите се да сте повезани на ВиФи или мобилне податке како бисте освежили и добили коментар на контакт."
+ },
+ "groupDetailScreen": {
+ "addNewGroup": "Додај нову групу",
+ "selectCoaches": "Изаберите Групни тренер",
+ "searchGroups": "Претражите групе",
+ "searchPeerGroups": "Претражите групе вршњака",
+ "childGroup": "Дечија група",
+ "searchChildGroups": "Претражите дечје групе",
+ "addMember": "Додај члана",
+ "noGroupCommentPlacheHolder": "Тренутно нема доступних коментара групе.",
+ "noGroupCommentPlacheHolder1": "Можда је дошло до проблема при преузимању са ваше веб локације. Превуците надоле да бисте покушали да освежите и покушајте поново.",
+ "noGroupCommentPlacheHolderOffline": "Тренутно сте ван мреже. Уверите се да сте повезани на ВиФи или мобилне податке како бисте освежили и добили коментар групе.",
+ "selectLocations": "Изаберите Лоцатионс",
+ "noMembersMessage": "Нема чланова. Додирните овде или на Уреди да бисте додали неке чланове у ову групу.",
+ "groupName": {
+ "label": "Назив групе",
+ "error": "Име је обавезно"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Састанак заказан",
+ "quick_button_meeting_postponed": "Састанак одложен",
+ "quick_button_meeting_complete": "Састанак завршен"
+ }
+ },
+ "notificationsScreen": {
+ "notifications": "Обавештења",
+ "loadMore": "Учитај више",
+ "new": "Нова",
+ "unRead": "Непрочитано",
+ "all": "Све",
+ "markAll": "Означи све",
+ "dontHaveNotificationsUnread": "Нема непрочитаних обавештења",
+ "dontHaveNotifications": "Нема обавештења"
+ },
+ "groupsScreen": {
+ "noGroupPlacheHolder": "Тренутно нема доступних група.",
+ "noGroupPlacheHolder1": "Можда је дошло до проблема при преузимању са ваше веб локације. Превуците надоле да бисте покушали да освежите и покушајте поново.",
+ "noGroupPlacheHolderOffline": "Тренутно сте ван мреже. Уверите се да сте повезани на ВиФи или мобилне податке како бисте освежили и прибавили своје групе."
+ },
+ "appRestart": {
+ "message": "Апликација ће се поново покренути да би применила следећу конфигурацију:",
+ "button": "Ок",
+ "textDirection": "Смер текста",
+ "selectedLanguage": "Одабрани језик"
+ }
+}
diff --git a/languages/sr.test.js b/languages/sr.test.js
new file mode 100644
index 00000000..a68a5af7
--- /dev/null
+++ b/languages/sr.test.js
@@ -0,0 +1,14 @@
+import i18n from '.';
+const locale = 'sr';
+
+describe('languages/' + locale, () => {
+ beforeAll(() => i18n.setLocale(locale, false));
+
+ test('test missing translation', () => {
+ expect(i18n.t('global.zz')).toEqual('[missing "' + locale + '.global.zz" translation]');
+ });
+
+ test('test global.success.save translation', () => {
+ expect(i18n.t('global.success.save')).toEqual('Подаци су успешно сачувани!');
+ });
+});
diff --git a/languages/sw.json b/languages/sw.json
index eaf844b1..937c4d9e 100644
--- a/languages/sw.json
+++ b/languages/sw.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Andika maoni yako au daftari hapa",
"requiredField": "Sehemu inayohitajika",
"edit": "Hariri",
+ "delete": "Futa",
"cancel": "Ghairi",
"save": "Okoa",
"online": "Mtandaoni",
@@ -25,13 +26,9 @@
"membersActivity": "Wajumbe",
"moreFields": "Mashamba Zaidi",
"nameRequired": "Jina linalohitajika",
- "close": "Karibu"
- },
- "appRestart": {
- "message": "Maombi yataanza tena kutumia usanidi ufuatao:",
- "button": "sawa",
- "textDirection": "Miongozo ya maandishi",
- "selectedLanguage": "Lugha iliyochaguliwa"
+ "close": "Karibu",
+ "editComment": "Hariri",
+ "deleteComment": "Futa"
},
"loginScreen": {
"domain": {
@@ -71,15 +68,15 @@
"rememberPassword": "Kumbuka Nenosiri",
"rememberPasswordActive": "Endelea kuwezeshwa",
"rememberPasswordInactive": "Endelea kuwa umelemazwa",
- "remove": "Ondoa msimbo wa Pini",
- "set": "Weka nambari ya PIN",
+ "remove": "Ondoa",
+ "set": "Weka",
"pinCode": "Nambari ya siri",
- "enterPin": "Ingiza msimbo wa pini",
+ "enterPin": "Ingiza PIN",
"setPin": "Weka PIN mpya",
- "incorrectPin": "Nambari ya Pini isiyo sahihi",
- "savedPinCode": "Nambari ya pini iliyohifadhiwa kikamilifu!",
- "removedPinCode": "Nambari ya pini imeondolewa vyema!",
- "close": "karibu"
+ "incorrectPin": "PIN isiyo sahihi",
+ "savedPinCode": "Nambari ya siri imehifadhiwa kwa mafanikio",
+ "removedPinCode": "Nambari ya siri imeondolewa kwa mafanikio",
+ "close": "Funga"
},
"contactDetailScreen": {
"addNewContact": "Ongeza Mawasiliano Mpya",
@@ -121,6 +118,11 @@
"groupName": {
"label": "Jina la Kikundi",
"error": "Jina inahitajika"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Mkutano Umepangwa",
+ "quick_button_meeting_postponed": "Mkutano Ulihairishwa",
+ "quick_button_meeting_complete": "Mkutano Umekamilika"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "Hakuna vikundi yoyote vinavyopatikana kwa sasa.",
"noGroupPlacheHolder1": "Kunaweza kuwa na shida kuzipata kutoka kwa wavuti yako. Buruta chini kujaribu kujaribu kuburudisha na kujaribu tena.",
"noGroupPlacheHolderOffline": "Hivi sasa uko nje ya mkondo. Hakikisha umeunganishwa na wifi au data ya rununu ili kuburudisha na upate vikundi vyako."
+ },
+ "appRestart": {
+ "message": "Programu itaanza tena kutumia usanidi ufuatao:",
+ "button": "Sawa",
+ "textDirection": "Mwelekeo wa maandishi",
+ "selectedLanguage": "Lugha iliyochaguliwa"
}
}
diff --git a/languages/tr.json b/languages/tr.json
index 913484a3..d0b9dc25 100644
--- a/languages/tr.json
+++ b/languages/tr.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "Yorumunu veya notunu buraya yaz",
"requiredField": "Gerekli alan",
"edit": "Düzenle",
+ "delete": "Sil",
"cancel": "İptal et",
"save": "kaydet",
"online": "Çevrimiçi",
@@ -25,13 +26,9 @@
"membersActivity": "Üyeler",
"moreFields": "Diğer Alanlar",
"nameRequired": "İsim (gerekli",
- "close": "Kapat"
- },
- "appRestart": {
- "message": "Aşağıdaki yapılandırmayı uygulamak için uygulama yeniden başlatılır:",
- "button": "tamam",
- "textDirection": "Metin yönü",
- "selectedLanguage": "Seçilen dil"
+ "close": "Kapat",
+ "editComment": "Düzenle",
+ "deleteComment": "Sil"
},
"loginScreen": {
"domain": {
@@ -71,15 +68,15 @@
"rememberPassword": "şifre hatırlamak",
"rememberPasswordActive": "Oturum açmayı etkin tut",
"rememberPasswordInactive": "Giriş yapmayı devre dışı bırak",
- "remove": "PIN kodunu kaldır",
- "set": "PIN kodunu ayarla",
+ "remove": "Kaldırmak",
+ "set": "Ayarlamak",
"pinCode": "PIN kodu",
- "enterPin": "PIN kodunu girin",
- "setPin": "Yeni PIN ayarla",
- "incorrectPin": "Yanlış PIN kodu",
- "savedPinCode": "PIN kodu başarıyla kaydedildi!",
- "removedPinCode": "PIN kodu başarıyla kaldırıldı!",
- "close": "kapat"
+ "enterPin": "PIN girin",
+ "setPin": "Yeni PIN belirleyin",
+ "incorrectPin": "Yanlış PIN",
+ "savedPinCode": "PIN kodu başarıyla kaydedildi",
+ "removedPinCode": "PIN kodu başarıyla kaldırıldı",
+ "close": "Kapat"
},
"contactDetailScreen": {
"addNewContact": "Yeni bağlantı ekle",
@@ -121,6 +118,11 @@
"groupName": {
"label": "Grup ismi",
"error": "İsim gerekli"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "Toplantı Planlandı",
+ "quick_button_meeting_postponed": "Toplantı Ertelendi",
+ "quick_button_meeting_complete": "Toplantı Tamamlandı"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "Şu anda kullanılabilir grup yok.",
"noGroupPlacheHolder1": "Bunları sitenizden alırken bir sorun olabilir. Yenilemeyi denemek için aşağı sürükleyin ve tekrar deneyin.",
"noGroupPlacheHolderOffline": "Şu anda çevrimdışısınız. Gruplarınızı yenilemek ve almak için kablosuz bağlantıya veya mobil verilere bağlı olduğunuzdan emin olun."
+ },
+ "appRestart": {
+ "message": "Aşağıdaki yapılandırmayı uygulamak için uygulama yeniden başlatılacak:",
+ "button": "Tamam",
+ "textDirection": "Metin yönü",
+ "selectedLanguage": "Seçilen dil"
}
}
diff --git a/languages/zhCn.json b/languages/zhCn.json
index 452180dc..00c2523a 100644
--- a/languages/zhCn.json
+++ b/languages/zhCn.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "在这里写下您的评论或注释",
"requiredField": "必填项目",
"edit": "编辑",
+ "delete": "删除",
"cancel": "取消",
"save": "保存",
"online": "线上",
@@ -25,13 +26,9 @@
"membersActivity": "会员",
"moreFields": "更多领域",
"nameRequired": "姓名必填",
- "close": "关"
- },
- "appRestart": {
- "message": "该应用程序将重新启动以应用以下配置:",
- "button": "好",
- "textDirection": "文字方向",
- "selectedLanguage": "所选语言"
+ "close": "关",
+ "editComment": "编辑",
+ "deleteComment": "删除"
},
"loginScreen": {
"domain": {
@@ -71,14 +68,14 @@
"rememberPassword": "记住密码",
"rememberPasswordActive": "保持登录状态",
"rememberPasswordInactive": "保持登录状态已禁用",
- "remove": "删除PIN码",
- "set": "设置PIN码",
+ "remove": "去掉",
+ "set": "组",
"pinCode": "PIN码",
- "enterPin": "输入PIN码",
+ "enterPin": "输入密码",
"setPin": "设置新密码",
- "incorrectPin": "PIN码不正确",
- "savedPinCode": "PIN码已成功保存!",
- "removedPinCode": "PIN码已成功删除!",
+ "incorrectPin": "PIN码错误",
+ "savedPinCode": "PIN码已成功保存",
+ "removedPinCode": "PIN码已成功删除",
"close": "关"
},
"contactDetailScreen": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "组的名字",
"error": "名称为必填项"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "会议预定",
+ "quick_button_meeting_postponed": "会议推迟",
+ "quick_button_meeting_complete": "会议完成"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "当前没有任何组。",
"noGroupPlacheHolder1": "从您的网站获取它们可能存在问题。向下拖动以尝试刷新,然后重试。",
"noGroupPlacheHolderOffline": "您目前离线。确保您已连接到wifi或移动数据,以便刷新并分组。"
+ },
+ "appRestart": {
+ "message": "该应用程序将重新启动以应用以下配置:",
+ "button": "好",
+ "textDirection": "文字方向",
+ "selectedLanguage": "所选语言"
}
}
diff --git a/languages/zhTw.json b/languages/zhTw.json
index f79a718e..ee27119b 100644
--- a/languages/zhTw.json
+++ b/languages/zhTw.json
@@ -16,6 +16,7 @@
"writeYourCommentNoteHere": "在這裡寫下您的評論或註釋",
"requiredField": "必填項目",
"edit": "編輯",
+ "delete": "刪除",
"cancel": "取消",
"save": "保存",
"online": "線上",
@@ -25,13 +26,9 @@
"membersActivity": "會員",
"moreFields": "更多領域",
"nameRequired": "姓名必填",
- "close": "關"
- },
- "appRestart": {
- "message": "該應用程序將重新啟動以應用以下配置:",
- "button": "好",
- "textDirection": "文字方向",
- "selectedLanguage": "所選語言"
+ "close": "關",
+ "editComment": "編輯",
+ "deleteComment": "刪除"
},
"loginScreen": {
"domain": {
@@ -71,14 +68,14 @@
"rememberPassword": "記住密碼",
"rememberPasswordActive": "保持登錄狀態",
"rememberPasswordInactive": "保持登錄狀態已禁用",
- "remove": "刪除PIN碼",
- "set": "設置PIN碼",
+ "remove": "去掉",
+ "set": "組",
"pinCode": "PIN碼",
- "enterPin": "輸入PIN碼",
+ "enterPin": "輸入密碼",
"setPin": "設置新密碼",
- "incorrectPin": "PIN碼不正確",
- "savedPinCode": "PIN碼已成功保存!",
- "removedPinCode": "PIN碼已成功刪除!",
+ "incorrectPin": "PIN碼錯誤",
+ "savedPinCode": "PIN碼已成功保存",
+ "removedPinCode": "PIN碼已成功刪除",
"close": "關"
},
"contactDetailScreen": {
@@ -121,6 +118,11 @@
"groupName": {
"label": "組的名字",
"error": "名稱為必填項"
+ },
+ "fab": {
+ "quick_button_meeting_scheduled": "會議預定",
+ "quick_button_meeting_postponed": "會議推遲",
+ "quick_button_meeting_complete": "會議完成"
}
},
"notificationsScreen": {
@@ -137,5 +139,11 @@
"noGroupPlacheHolder": "當前沒有任何組。",
"noGroupPlacheHolder1": "從您的網站獲取它們可能存在問題。向下拖動以嘗試刷新,然後重試。",
"noGroupPlacheHolderOffline": "您目前離線。確保您已連接到wifi或移動數據,以便刷新並分組。"
+ },
+ "appRestart": {
+ "message": "該應用程序將重新啟動以應用以下配置:",
+ "button": "好",
+ "textDirection": "文字方向",
+ "selectedLanguage": "所選語言"
}
}
diff --git a/package-lock.json b/package-lock.json
index b289181e..47d6ce5b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1356,12 +1356,12 @@
}
},
"@expo/configure-splash-screen": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/@expo/configure-splash-screen/-/configure-splash-screen-0.1.12.tgz",
- "integrity": "sha512-XvXZEmRaHmuO4/oJnE4cD2VFwYQec7kXBq0Ki9NtSdNHmGWE8XuXslZpn9anORcTjas/X0p9KtJbRsYQVVqbww==",
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/@expo/configure-splash-screen/-/configure-splash-screen-0.1.15.tgz",
+ "integrity": "sha512-jKall/3aq3g/dQd0gPijsCxHyPXWh8rq/F2h0IYf1mcixlrMGTTFl/0um48SMJzyEg4HYMe4w8thn79vseI+AA==",
"requires": {
- "@react-native-community/cli-platform-android": "4.7.0",
- "@react-native-community/cli-platform-ios": "4.7.0",
+ "@react-native-community/cli-platform-android": "^4.10.0",
+ "@react-native-community/cli-platform-ios": "^4.10.0",
"color-string": "^1.5.3",
"commander": "^5.1.0",
"core-js": "^3.6.5",
@@ -1372,6 +1372,119 @@
"xml-js": "^1.6.11"
},
"dependencies": {
+ "@react-native-community/cli-platform-android": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-4.13.0.tgz",
+ "integrity": "sha512-3i8sX8GklEytUZwPnojuoFbCjIRzMugCdzDIdZ9UNmi/OhD4/8mLGO0dgXfT4sMWjZwu3qjy45sFfk2zOAgHbA==",
+ "requires": {
+ "@react-native-community/cli-tools": "^4.13.0",
+ "chalk": "^3.0.0",
+ "execa": "^1.0.0",
+ "fs-extra": "^8.1.0",
+ "glob": "^7.1.3",
+ "jetifier": "^1.6.2",
+ "lodash": "^4.17.15",
+ "logkitty": "^0.7.1",
+ "slash": "^3.0.0",
+ "xmldoc": "^1.1.2"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ }
+ }
+ },
+ "@react-native-community/cli-platform-ios": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-4.13.0.tgz",
+ "integrity": "sha512-6THlTu8zp62efkzimfGr3VIuQJ2514o+vScZERJCV1xgEi8XtV7mb/ZKt9o6Y9WGxKKkc0E0b/aVAtgy+L27CA==",
+ "requires": {
+ "@react-native-community/cli-tools": "^4.13.0",
+ "chalk": "^3.0.0",
+ "glob": "^7.1.3",
+ "js-yaml": "^3.13.1",
+ "lodash": "^4.17.15",
+ "plist": "^3.0.1",
+ "xcode": "^2.0.0"
+ },
+ "dependencies": {
+ "xcode": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/xcode/-/xcode-2.1.0.tgz",
+ "integrity": "sha512-uCrmPITrqTEzhn0TtT57fJaNaw8YJs1aCzs+P/QqxsDbvPZSv7XMPPwXrKvHtD6pLjBM/NaVwraWJm8q83Y4iQ==",
+ "requires": {
+ "simple-plist": "^1.0.0",
+ "uuid": "^3.3.2"
+ }
+ }
+ }
+ },
+ "@react-native-community/cli-tools": {
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-4.13.0.tgz",
+ "integrity": "sha512-s4f489h5+EJksn4CfheLgv5PGOM0CDmK1UEBLw2t/ncWs3cW2VI7vXzndcd/WJHTv3GntJhXDcJMuL+Z2IAOgg==",
+ "requires": {
+ "chalk": "^3.0.0",
+ "lodash": "^4.17.15",
+ "mime": "^2.4.1",
+ "node-fetch": "^2.6.0",
+ "open": "^6.2.0",
+ "shell-quote": "1.6.1"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
+ },
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
"deep-equal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz",
@@ -1392,6 +1505,147 @@
"which-collection": "^1.0.1",
"which-typed-array": "^1.1.2"
}
+ },
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "logkitty": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz",
+ "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==",
+ "requires": {
+ "ansi-fragments": "^0.2.1",
+ "dayjs": "^1.8.15",
+ "yargs": "^15.1.0"
+ }
+ },
+ "node-fetch": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "requires": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
}
}
},
@@ -3072,7 +3326,6 @@
"glob": "^7.1.3",
"jetifier": "^1.6.2",
"lodash": "^4.17.15",
- "logkitty": "^0.6.0",
"slash": "^3.0.0",
"xmldoc": "^1.1.2"
},
@@ -3307,9 +3560,9 @@
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"node-fetch": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
- "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"supports-color": {
"version": "7.1.0",
@@ -3452,9 +3705,9 @@
},
"dependencies": {
"node-fetch": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
- "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
}
}
},
@@ -3540,8 +3793,7 @@
"opn": "^5.4.0",
"r2": "^2.0.1",
"read-env": "^1.3.0",
- "xcode": "2.0.0",
- "yargs": "^12.0.2"
+ "xcode": "2.0.0"
},
"dependencies": {
"chardet": {
@@ -5324,31 +5576,6 @@
"tiny-emitter": "^2.0.0"
}
},
- "cliui": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
- "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
- "requires": {
- "string-width": "^2.1.1",
- "strip-ansi": "^4.0.0",
- "wrap-ansi": "^2.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
- "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
- },
- "strip-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
- "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
- "requires": {
- "ansi-regex": "^3.0.0"
- }
- }
- }
- },
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
@@ -5360,11 +5587,6 @@
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true
},
- "code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
- },
"collect-v8-coverage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
@@ -5657,18 +5879,18 @@
}
},
"cross-fetch": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.5.tgz",
- "integrity": "sha512-FFLcLtraisj5eteosnX1gf01qYDCOc4fDy0+euOt8Kn9YBY2NtXL/pCoYPavw24NIQkQqm5ZOLsGD5Zzj0gyew==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz",
+ "integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==",
"dev": true,
"requires": {
- "node-fetch": "2.6.0"
+ "node-fetch": "2.6.1"
},
"dependencies": {
"node-fetch": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
- "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
"dev": true
}
}
@@ -6076,14 +6298,6 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
- "encoding": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
- "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
- "requires": {
- "iconv-lite": "^0.6.2"
- }
- },
"end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -7847,11 +8061,6 @@
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
"integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg=="
},
- "get-caller-file": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
- },
"get-own-enumerable-property-symbols": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
@@ -8321,14 +8530,6 @@
"resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.7.1.tgz",
"integrity": "sha512-xrRzCeda5ZC0u0yRN+dMdidtda0N+f7t7Pek0ajWb+iyKqSGdrMmuBtbNpWJWY5N4Th0cxbp/BR57zSPdrM3Rw=="
},
- "iconv-lite": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
- "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- }
- },
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@@ -8533,11 +8734,6 @@
"loose-envify": "^1.0.0"
}
},
- "invert-kv": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
- "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
- },
"ip-regex": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
@@ -8880,7 +9076,6 @@
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
"integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
"requires": {
- "node-fetch": "^1.0.1",
"whatwg-fetch": ">=0.10.0"
}
},
@@ -13122,14 +13317,6 @@
"language-subtag-registry": "~0.3.2"
}
},
- "lcid": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
- "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
- "requires": {
- "invert-kv": "^2.0.0"
- }
- },
"left-pad": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
@@ -13792,16 +13979,6 @@
}
}
},
- "logkitty": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.6.1.tgz",
- "integrity": "sha512-cHuXN8qUZuzX/7kB6VyS7kB4xyD24e8gyHXIFNhIv+fjW3P+jEXNUhj0o/7qWJtv7UZpbnPgUqzu/AZQ8RAqxQ==",
- "requires": {
- "ansi-fragments": "^0.2.1",
- "dayjs": "^1.8.15",
- "yargs": "^12.0.5"
- }
- },
"lolex": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz",
@@ -13861,14 +14038,6 @@
"tmpl": "1.0.x"
}
},
- "map-age-cleaner": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
- "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
- "requires": {
- "p-defer": "^1.0.0"
- }
- },
"map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
@@ -13904,16 +14073,6 @@
"buffer-alloc": "^1.1.0"
}
},
- "mem": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
- "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
- "requires": {
- "map-age-cleaner": "^0.1.1",
- "mimic-fn": "^2.0.0",
- "p-is-promise": "^2.0.0"
- }
- },
"memoizerific": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz",
@@ -14100,9 +14259,9 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"node-fetch": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
- "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"p-limit": {
"version": "2.3.0",
@@ -14626,7 +14785,8 @@
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
},
"min-document": {
"version": "2.19.0",
@@ -14863,15 +15023,6 @@
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
},
- "node-fetch": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
- "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
- "requires": {
- "encoding": "^0.1.11",
- "is-stream": "^1.0.1"
- }
- },
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -15005,11 +15156,6 @@
"resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
"integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="
},
- "number-is-nan": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
- },
"nwsapi": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
@@ -15254,26 +15400,11 @@
"wcwidth": "^1.0.1"
}
},
- "os-locale": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
- "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
- "requires": {
- "execa": "^1.0.0",
- "lcid": "^2.0.0",
- "mem": "^4.0.0"
- }
- },
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
- "p-defer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
- "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
- },
"p-each-series": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz",
@@ -15285,11 +15416,6 @@
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
},
- "p-is-promise": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
- "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
- },
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
@@ -15990,9 +16116,9 @@
},
"dependencies": {
"node-fetch": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
- "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
}
}
},
@@ -17329,11 +17455,6 @@
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
- "require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
- },
"requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@@ -19151,48 +19272,6 @@
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
},
- "wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
- "requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- }
- }
- },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -19322,74 +19401,6 @@
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz",
"integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg=="
- },
- "yargs": {
- "version": "12.0.5",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
- "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
- "requires": {
- "cliui": "^4.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^1.0.1",
- "os-locale": "^3.0.0",
- "require-directory": "^2.1.1",
- "require-main-filename": "^1.0.1",
- "set-blocking": "^2.0.0",
- "string-width": "^2.0.0",
- "which-module": "^2.0.0",
- "y18n": "^3.2.1 || ^4.0.0",
- "yargs-parser": "^11.1.1"
- },
- "dependencies": {
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
- }
- }
- },
- "yargs-parser": {
- "version": "11.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
- "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
}
}
}
diff --git a/screens/Contact/ContactDetailScreen.js b/screens/Contact/ContactDetailScreen.js
index 25c3a193..34583a44 100644
--- a/screens/Contact/ContactDetailScreen.js
+++ b/screens/Contact/ContactDetailScreen.js
@@ -15,13 +15,13 @@ import {
Linking,
BackHandler,
ActivityIndicator,
+ KeyboardAvoidingView,
} from 'react-native';
-
import { connect } from 'react-redux';
import ExpoFileSystemStorage from 'redux-persist-expo-filesystem';
import PropTypes from 'prop-types';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
-import { Label, Input, Icon, Picker, DatePicker, Textarea } from 'native-base';
+import { Label, Input, Icon, Picker, DatePicker, Textarea, Button } from 'native-base';
import Toast from 'react-native-easy-toast';
import { Col, Row, Grid } from 'react-native-easy-grid';
import ProgressBarAnimated from 'react-native-progress-bar-animated';
@@ -31,7 +31,8 @@ import { TabView, TabBar } from 'react-native-tab-view';
import { NavigationActions, StackActions } from 'react-navigation';
import MentionsTextInput from 'react-native-mentions';
import ParsedText from 'react-native-parsed-text';
-import * as Sentry from 'sentry-expo';
+//import * as Sentry from 'sentry-expo';
+import { BlurView } from 'expo-blur';
import moment from '../../languages/moment';
import sharedTools from '../../shared';
@@ -43,8 +44,13 @@ import {
getByIdEnd,
getActivitiesByContact,
saveEnd,
+ deleteComment,
+ loadingFalse,
+ updatePrevious,
} from '../../store/actions/contacts.actions';
+import { updatePrevious as updatePreviousGroups } from '../../store/actions/groups.actions';
import Colors from '../../constants/Colors';
+import statusIcon from '../../assets/icons/status.png';
import hasBibleIcon from '../../assets/icons/book-bookmark.png';
import readingBibleIcon from '../../assets/icons/word.png';
import statesBeliefIcon from '../../assets/icons/language.png';
@@ -60,10 +66,11 @@ import { searchLocations } from '../../store/actions/groups.actions';
let toastSuccess;
let toastError;
-const containerPadding = 35;
+const containerPadding = 20;
const windowWidth = Dimensions.get('window').width;
const progressBarWidth = windowWidth - 100;
const milestonesGridSize = windowWidth + 5;
+const windowHeight = Dimensions.get('window').height;
let keyboardDidShowListener, keyboardDidHideListener, focusListener, hardwareBackPressListener;
//const hasNotch = Platform.OS === 'android' && StatusBar.currentHeight > 25;
//const extraNotchHeight = hasNotch ? StatusBar.currentHeight : 0;
@@ -117,9 +124,17 @@ const styles = StyleSheet.create({
},
tabStyle: { backgroundColor: '#FFFFFF' },
textStyle: { color: 'gray' },
+ fieldsIcons: {
+ height: 22,
+ width: 22,
+ },
addRemoveIcons: {
fontSize: 30,
+ marginRight: 0,
+ color: Colors.addRemoveIcons,
},
+ addIcons: { color: 'green' },
+ removeIcons: { color: 'red' },
// Social Media Field
socialMediaNames: {
color: Colors.grayDark,
@@ -128,22 +143,23 @@ const styles = StyleSheet.create({
// Form
formContainer: {
paddingTop: 10,
- paddingBottom: 80,
+ paddingBottom: 100,
paddingLeft: containerPadding,
paddingRight: containerPadding,
},
formRow: {
- paddingTop: 20,
- paddingBottom: 20,
+ paddingTop: 15,
+ paddingBottom: 15,
width: '100%',
},
formIconLabel: {
marginLeft: 10,
width: 'auto',
+ marginBottom: 'auto',
},
formIcon: {
color: Colors.tintColor,
- fontSize: 25,
+ fontSize: 22,
marginTop: 'auto',
marginBottom: 'auto',
},
@@ -159,17 +175,18 @@ const styles = StyleSheet.create({
formDivider: {
borderBottomColor: '#CCCCCC',
borderBottomWidth: 1,
- marginLeft: 10,
- marginRight: 10,
},
formIconLabelCol: {
width: 35,
},
formIconLabelView: {
alignItems: 'center',
+ marginTop: 'auto',
+ marginBottom: 'auto',
},
formFieldMargin: {
marginTop: 20,
+ marginBottom: 10,
},
// Progress Section
progressIcon: { height: '100%', width: '100%' },
@@ -224,9 +241,8 @@ const styles = StyleSheet.create({
},
noCommentsContainer: {
padding: 20,
- textAlignVertical: 'top',
- textAlign: 'center',
- height: 300,
+ height: '90%',
+ transform: [{ scaleY: -1 }],
},
noCommentsImage: {
opacity: 0.5,
@@ -235,19 +251,10 @@ const styles = StyleSheet.create({
padding: 10,
},
noCommentsText: {
- textAlignVertical: 'center',
textAlign: 'center',
fontWeight: 'bold',
color: '#A8A8A8',
- padding: 5,
- },
- noCommentsTextOffilne: {
- textAlignVertical: 'center',
- textAlign: 'center',
- fontWeight: 'bold',
- color: '#A8A8A8',
- backgroundColor: '#fff2ac',
- padding: 5,
+ marginTop: 10,
},
contactTextField: {
borderBottomWidth: 1,
@@ -320,6 +327,44 @@ const styles = StyleSheet.create({
fontSize: 12,
color: 'rgba(0,0,0,0.6)',
},
+ // Edit/Delete comment dialog
+ dialogBackground: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ },
+ dialogBox: {
+ backgroundColor: '#FFFFFF',
+ padding: 20,
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ height: windowHeight - windowHeight * 0.55,
+ width: windowWidth - windowWidth * 0.1,
+ marginTop: windowHeight * 0.1,
+ },
+ dialogButton: {
+ backgroundColor: Colors.tintColor,
+ borderRadius: 5,
+ width: 100,
+ marginTop: 20,
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ },
+ dialogContent: {
+ height: '100%',
+ width: '100%',
+ fontSize: 20,
+ textAlign: 'center',
+ color: Colors.grayDark,
+ marginBottom: 5,
+ },
+ dialogComment: {
+ borderWidth: 1,
+ borderRadius: 5,
+ borderStyle: 'solid',
+ borderColor: '#B4B4B4',
+ color: Colors.tintColor,
+ },
});
const initialState = {
@@ -331,22 +376,29 @@ const initialState = {
peopleGroups: [],
geonames: [],
loadedLocal: false,
- comments: [],
+ comments: {
+ data: [],
+ pagination: {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ },
+ },
loadComments: false,
loadingMoreComments: false,
- totalComments: 0,
- commentsOffset: 0,
- commentsLimit: 10,
- activities: [],
+ activities: {
+ data: [],
+ pagination: {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ },
+ },
loadActivities: false,
loadingMoreActivities: false,
- totalActivities: 0,
- activitiesOffset: 0,
- activitiesLimit: 10,
comment: '',
progressBarValue: 0,
overallStatusBackgroundColor: '#ffffff',
- renderFab: true,
showAssignedToModal: false,
loading: false,
moreFields: false,
@@ -380,7 +432,12 @@ const initialState = {
connectionGroups: [],
unmodifiedConnectionGroups: [],
assignedToContacts: [],
- unmodifedAssignedToContacts: []
+ unmodifedAssignedToContacts: [],
+ commentDialog: {
+ toggle: false,
+ data: {},
+ delete: false,
+ },
};
const safeFind = (found, prop) => {
@@ -401,14 +458,14 @@ class ContactDetailScreen extends React.Component {
: i18n.t('contactDetailScreen.addNewContact');
let headerRight = () => (
-
+
{i18n.t('global.save')}
@@ -420,14 +477,14 @@ class ContactDetailScreen extends React.Component {
if (params.onEnableEdit && params.contactId && params.onlyView) {
headerRight = () => (
-
+
{i18n.t('global.edit')}
@@ -439,10 +496,8 @@ class ContactDetailScreen extends React.Component {
{
- params.backButtonTap();
- }}
- style={{ paddingLeft: 16, color: '#FFFFFF', paddingRight: 16 }}
+ onPress={params.backButtonTap}
+ style={{ paddingLeft: 16, color: Colors.onPressIcons, paddingRight: 16 }}
/>
);
} else {
@@ -452,11 +507,11 @@ class ContactDetailScreen extends React.Component {
type="AntDesign"
name="close"
style={[
- { color: '#FFFFFF', marginTop: 'auto', marginBottom: 'auto' },
+ { color: Colors.onPressIcons, marginTop: 'auto', marginBottom: 'auto' },
self && self.props.isRTL ? { paddingRight: 16 } : { paddingLeft: 16 },
]}
/>
-
+
{i18n.t('global.cancel')}
@@ -475,13 +530,13 @@ class ContactDetailScreen extends React.Component {
fontWeight: 'bold',
width: params.onlyView
? Platform.select({
- android: 200,
- ios: 180,
- })
+ android: 200,
+ ios: 180,
+ })
: Platform.select({
- android: 180,
- ios: 140,
- }),
+ android: 180,
+ ios: 140,
+ }),
marginLeft: params.onlyView ? undefined : 25,
},
};
@@ -494,12 +549,22 @@ class ContactDetailScreen extends React.Component {
componentDidMount() {
const { navigation } = this.props;
this.onLoad();
- navigation.setParams({
- onEnableEdit: this.onEnableEdit,
- onDisableEdit: this.onDisableEdit,
- onSaveContact: this.onSaveContact,
- backButtonTap: this.backButtonTap,
- });
+
+ let params = {
+ onEnableEdit: this.onEnableEdit.bind(this),
+ onDisableEdit: this.onDisableEdit.bind(this),
+ onSaveContact: this.onSaveContact.bind(this),
+ backButtonTap: this.backButtonTap.bind(this),
+ };
+ // Add afterBack param to execute 'parents' functions (ContactsView, NotificationsView)
+ if (!navigation.state.params.afterBack) {
+ params = {
+ ...params,
+ afterBack: this.afterBack.bind(this),
+ };
+ }
+ navigation.setParams(params);
+
keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
this.keyboardDidShow.bind(this),
@@ -509,34 +574,21 @@ class ContactDetailScreen extends React.Component {
this.keyboardDidHide.bind(this),
);
focusListener = navigation.addListener('didFocus', () => {
- if (
- typeof this.props.navigation.state.params.contactId !== 'undefined' &&
- this.state.loadedLocal
- ) {
- this.setState(
- {
- loading: false,
- },
- () => {
- this.onRefresh(this.props.navigation.state.params.contactId);
- },
- );
+ //Focus on 'detail mode' (going back or open detail view)
+ if (typeof this.props.navigation.state.params.contactId !== 'undefined') {
+ this.props.loadingFalse();
+ this.onRefresh(this.props.navigation.state.params.contactId, true);
}
});
+ // Android bottom back button listener
hardwareBackPressListener = BackHandler.addEventListener('hardwareBackPress', () => {
- sharedTools.onlyExecuteLastCall(
- null,
- () => {
- this.backButtonTap();
- },
- 1000,
- );
+ this.props.navigation.state.params.backButtonTap();
return true;
});
}
componentDidCatch(error, errorInfo) {
- Sentry.captureException(errorInfo);
+ //Sentry.captureException(errorInfo);
}
componentWillUnmount() {
@@ -551,35 +603,22 @@ class ContactDetailScreen extends React.Component {
contact,
loading,
comments,
- totalComments,
loadingComments,
activities,
- totalActivities,
loadingActivities,
- newComment,
foundGeonames,
} = nextProps;
let newState = {
...prevState,
loading,
- comments: comments || prevState.comments,
- totalComments: totalComments || prevState.totalComments,
+ comments: prevState.comments,
loadComments: loadingComments,
- activities: activities || prevState.activities,
- totalActivities: totalActivities || prevState.totalActivities,
+ activities: prevState.activities,
loadActivities: loadingActivities,
contact: prevState.contact,
unmodifiedContact: prevState.unmodifiedContact,
};
- // NEW COMMENT
- if (newComment) {
- newState.comments.unshift(newComment);
- newState = {
- ...newState,
- comments: newState.comments,
- };
- }
// SAVE / GET BY ID
if (contact) {
newState = {
@@ -591,9 +630,6 @@ class ContactDetailScreen extends React.Component {
...contact,
},
};
- if (newState.contact.oldID) {
- delete newState.contact.oldID;
- }
if (newState.contact.overall_status) {
newState = {
...newState,
@@ -663,15 +699,16 @@ class ContactDetailScreen extends React.Component {
});
}
if (newState.contact.subassigned) {
-
// Clear collection
newState = {
...newState,
- subAssignedContacts: []
+ subAssignedContacts: [],
};
newState.contact.subassigned.values.forEach((subassignedContact) => {
- const foundSubassigned = newState.usersContacts.find((user) => user.value === subassignedContact.value);
+ const foundSubassigned = newState.usersContacts.find(
+ (user) => user.value === subassignedContact.value,
+ );
if (!foundSubassigned) {
// Add non existent contact subassigned in subassigned list (user does not have access permission to this contacts)
newState = {
@@ -680,31 +717,31 @@ class ContactDetailScreen extends React.Component {
...newState.subAssignedContacts,
{
name: subassignedContact.name,
- value: subassignedContact.value
- }
+ value: subassignedContact.value,
+ },
],
unmodifiedSubAssignedContacts: [
...newState.unmodifiedSubAssignedContacts,
{
name: subassignedContact.name,
- value: subassignedContact.value
- }
- ]
+ value: subassignedContact.value,
+ },
+ ],
};
}
});
-
}
if (newState.contact.relation) {
-
// Clear collection
newState = {
...newState,
- relationContacts: []
+ relationContacts: [],
};
newState.contact.relation.values.forEach((relationContact) => {
- const foundRelation = newState.usersContacts.find((user) => user.value === relationContact.value);
+ const foundRelation = newState.usersContacts.find(
+ (user) => user.value === relationContact.value,
+ );
if (!foundRelation) {
// Add non existent contact relation in relation list (user does not have access permission to this contacts)
newState = {
@@ -713,31 +750,31 @@ class ContactDetailScreen extends React.Component {
...newState.relationContacts,
{
name: relationContact.name,
- value: relationContact.value
- }
+ value: relationContact.value,
+ },
],
unmodifiedRelationContacts: [
...newState.unmodifiedRelationContacts,
{
name: relationContact.name,
- value: relationContact.value
- }
- ]
+ value: relationContact.value,
+ },
+ ],
};
}
});
-
}
if (newState.contact.baptized_by) {
-
// Clear collection
newState = {
...newState,
- baptizedByContacts: []
+ baptizedByContacts: [],
};
newState.contact.baptized_by.values.forEach((baptizedByContact) => {
- const foundBaptized = newState.usersContacts.find((user) => user.value === baptizedByContact.value);
+ const foundBaptized = newState.usersContacts.find(
+ (user) => user.value === baptizedByContact.value,
+ );
if (!foundBaptized) {
// Add non existent contact relation in relation list (user does not have access permission to this contacts)
newState = {
@@ -746,31 +783,31 @@ class ContactDetailScreen extends React.Component {
...newState.baptizedByContacts,
{
name: baptizedByContact.name,
- value: baptizedByContact.value
- }
+ value: baptizedByContact.value,
+ },
],
unmodifiedBaptizedByContacts: [
...newState.unmodifiedBaptizedByContacts,
{
name: baptizedByContact.name,
- value: baptizedByContact.value
- }
- ]
+ value: baptizedByContact.value,
+ },
+ ],
};
}
});
-
}
if (newState.contact.baptized) {
-
// Clear collection
newState = {
...newState,
- baptizedContacts: []
+ baptizedContacts: [],
};
newState.contact.baptized.values.forEach((baptizedContact) => {
- const foundBaptized = newState.usersContacts.find((user) => user.value === baptizedContact.value);
+ const foundBaptized = newState.usersContacts.find(
+ (user) => user.value === baptizedContact.value,
+ );
if (!foundBaptized) {
// Add non existent contact baptized to list (user does not have access permission to this contacts)
newState = {
@@ -779,31 +816,31 @@ class ContactDetailScreen extends React.Component {
...newState.baptizedContacts,
{
name: baptizedContact.name,
- value: baptizedContact.value
- }
+ value: baptizedContact.value,
+ },
],
unmodifiedBaptizedContacts: [
...newState.unmodifiedBaptizedContacts,
{
name: baptizedContact.name,
- value: baptizedContact.value
- }
- ]
+ value: baptizedContact.value,
+ },
+ ],
};
}
});
-
}
if (newState.contact.coached_by) {
-
// Clear collection
newState = {
...newState,
- coachedByContacts: []
+ coachedByContacts: [],
};
newState.contact.coached_by.values.forEach((coachedByContact) => {
- const foundcoachedBy = newState.usersContacts.find((user) => user.value === coachedByContact.value);
+ const foundcoachedBy = newState.usersContacts.find(
+ (user) => user.value === coachedByContact.value,
+ );
if (!foundcoachedBy) {
// Add non existent contact coachedBy to list (user does not have access permission to this contacts)
newState = {
@@ -812,31 +849,31 @@ class ContactDetailScreen extends React.Component {
...newState.coachedByContacts,
{
name: coachedByContact.name,
- value: coachedByContact.value
- }
+ value: coachedByContact.value,
+ },
],
unmodifiedCoachedByContacts: [
...newState.unmodifiedCoachedByContacts,
{
name: coachedByContact.name,
- value: coachedByContact.value
- }
- ]
+ value: coachedByContact.value,
+ },
+ ],
};
}
});
-
}
if (newState.contact.coaching) {
-
// Clear collection
newState = {
...newState,
- coachedContacts: []
+ coachedContacts: [],
};
newState.contact.coaching.values.forEach((coachedContact) => {
- const foundCoached = newState.usersContacts.find((user) => user.value === coachedContact.value);
+ const foundCoached = newState.usersContacts.find(
+ (user) => user.value === coachedContact.value,
+ );
if (!foundCoached) {
// Add non existent contact coached to list (user does not have access permission to this contacts)
newState = {
@@ -845,27 +882,25 @@ class ContactDetailScreen extends React.Component {
...newState.coachedContacts,
{
name: coachedContact.name,
- value: coachedContact.value
- }
+ value: coachedContact.value,
+ },
],
unmodifiedCoachedContacts: [
...newState.unmodifiedCoachedContacts,
{
name: coachedContact.name,
- value: coachedContact.value
- }
- ]
+ value: coachedContact.value,
+ },
+ ],
};
}
});
-
}
if (newState.contact.groups) {
-
// Clear collection
newState = {
...newState,
- connectionGroups: []
+ connectionGroups: [],
};
newState.contact.groups.values.forEach((groupConnection) => {
@@ -878,86 +913,99 @@ class ContactDetailScreen extends React.Component {
...newState.connectionGroups,
{
name: groupConnection.name,
- value: groupConnection.value
- }
+ value: groupConnection.value,
+ },
],
unmodifiedConnectionGroups: [
...newState.unmodifiedConnectionGroups,
{
name: groupConnection.name,
- value: groupConnection.value
- }
- ]
+ value: groupConnection.value,
+ },
+ ],
};
}
});
-
}
if (newState.contact.assigned_to) {
-
// Clear collection
newState = {
...newState,
- assignedToContacts: []
+ assignedToContacts: [],
};
- let foundAssigned = newState.users.find((user) => user.key === newState.contact.assigned_to.key);
- if (!foundAssigned) {
- // Add non existent group to list (user does not have access permission to this groups)
- newState = {
- ...newState,
- assignedToContacts: [
- ...newState.assignedToContacts,
- {
- label: foundAssigned.label,
- key: foundAssigned.key
- }
- ],
- unmodifedAssignedToContacts: [
- ...newState.unmodifedAssignedToContacts,
- {
- label: foundAssigned.label,
- key: foundAssigned.key
- }
- ]
- };
- }
-
+ let foundAssigned = newState.users.find(
+ (user) => user.key === newState.contact.assigned_to.key,
+ );
+ if (!foundAssigned) {
+ // Add non existent group to list (user does not have access permission to this groups)
+ newState = {
+ ...newState,
+ assignedToContacts: [
+ ...newState.assignedToContacts,
+ {
+ label: newState.contact.assigned_to.label,
+ key: newState.contact.assigned_to.key,
+ },
+ ],
+ unmodifedAssignedToContacts: [
+ ...newState.unmodifedAssignedToContacts,
+ {
+ label: newState.contact.assigned_to.label,
+ key: newState.contact.assigned_to.key,
+ },
+ ],
+ };
+ }
}
}
// GET COMMENTS
if (comments) {
- // NEW COMMENTS (PAGINATION)
- if (prevState.commentsOffset > 0) {
+ if (
+ newState.contact.ID &&
+ Object.prototype.hasOwnProperty.call(comments, newState.contact.ID)
+ ) {
+ // NEW COMMENTS (PAGINATION)
+ if (comments[newState.contact.ID].pagination.offset > 0) {
+ newState = {
+ ...newState,
+ loadingMoreComments: false,
+ };
+ }
+ // ONLINE MODE: USE STATE PAGINATION - OFFLINE MODE: USE STORE PAGINATION
+ // UPDATE OFFSET
newState = {
...newState,
- comments: prevState.comments.concat(comments),
- loadingMoreComments: false,
+ comments: {
+ ...comments[newState.contact.ID],
+ },
};
}
- newState = {
- // UPDATE OFFSET
- ...newState,
- commentsOffset: prevState.commentsOffset + prevState.commentsLimit,
- };
}
- // GET ACTIVITITES
+ // GET ACTIVITIES
if (activities) {
- // NEW ACTIVITIES (PAGINATION)
- if (prevState.activitiesOffset > 0) {
+ if (
+ newState.contact.ID &&
+ Object.prototype.hasOwnProperty.call(activities, newState.contact.ID)
+ ) {
+ // NEW ACTIVITIES (PAGINATION)
+ if (activities[newState.contact.ID].pagination.offset > 0) {
+ newState = {
+ ...newState,
+ loadingMoreActivities: false,
+ };
+ }
+ // ONLINE MODE: USE STATE PAGINATION - OFFLINE MODE: USE STORE PAGINATION
+ // UPDATE OFFSET
newState = {
...newState,
- activities: prevState.activities.concat(activities),
- loadingMoreActivities: false,
+ activities: {
+ ...activities[newState.contact.ID],
+ },
};
}
- newState = {
- // UPDATE OFFSET
- ...newState,
- activitiesOffset: prevState.activitiesOffset + prevState.activitiesLimit,
- };
}
// GET FILTERED LOCATIONS
@@ -998,7 +1046,7 @@ class ContactDetailScreen extends React.Component {
// Same offline contact created in DB (AutoID to DBID)
if (
(typeof contact.ID !== 'undefined' && typeof this.state.contact.ID === 'undefined') ||
- contact.ID.toString() === this.state.contact.ID.toString() ||
+ (contact.ID && contact.ID.toString() === this.state.contact.ID.toString()) ||
(contact.oldID && contact.oldID === this.state.contact.ID.toString())
) {
// Highlight Updates -> Compare this.state.contact with contact and show differences
@@ -1010,6 +1058,21 @@ class ContactDetailScreen extends React.Component {
this.onSaveComment();
}
this.getContactByIdEnd();
+ // Add contact to 'previousContacts' array on creation
+ if (
+ !this.props.previousContacts.find(
+ (previousContact) => previousContact.contactId === parseInt(contact.ID),
+ )
+ ) {
+ this.props.updatePrevious([
+ ...this.props.previousContacts,
+ {
+ contactId: parseInt(contact.ID),
+ onlyView: true,
+ contactName: contact.title,
+ },
+ ]);
+ }
}
}
@@ -1021,10 +1084,11 @@ class ContactDetailScreen extends React.Component {
// Same offline contact created in DB (AutoID to DBID)
if (
(typeof contact.ID !== 'undefined' && typeof this.state.contact.ID === 'undefined') ||
- contact.ID.toString() === this.state.contact.ID.toString() ||
+ (contact.ID && contact.ID.toString() === this.state.contact.ID.toString()) ||
(contact.oldID && contact.oldID === this.state.contact.ID.toString())
) {
- this.onRefreshCommentsActivities(contact.ID);
+ // Highlight Updates -> Compare this.state.group with group and show differences
+ this.onRefreshCommentsActivities(contact.ID, true);
toastSuccess.show(
{i18n.t('global.success.save')}
@@ -1056,11 +1120,12 @@ class ContactDetailScreen extends React.Component {
3000,
);
}
-
+ // Fix to press back button in comments tab
if (prevProps.navigation.state.params.hideTabBar !== navigation.state.params.hideTabBar) {
if (!navigation.state.params.hideTabBar && this.state.executingBack) {
setTimeout(() => {
- this.executeBack(navigation, navigation.state.params);
+ navigation.goBack(null);
+ navigation.state.params.afterBack();
}, 1000);
}
}
@@ -1149,15 +1214,42 @@ class ContactDetailScreen extends React.Component {
},
);
} else {
- this.executeBack(navigation, params);
+ //Fix to returning using Android back button! -> goBack(null)
+ navigation.goBack(null);
+ navigation.state.params.afterBack();
}
};
- executeBack = (navigation, params) => {
- if (params.previousList.length > 0) {
- navigation.goBack();
- params.onBackFromSameScreen();
- } else if (params.fromNotificationView) {
+ afterBack = () => {
+ let { navigation } = this.props;
+ let newPreviousContacts = [...this.props.previousContacts];
+ newPreviousContacts.pop();
+ this.props.updatePrevious(newPreviousContacts);
+ if (newPreviousContacts.length > 0) {
+ this.props.loadingFalse();
+ let currentParams = {
+ ...newPreviousContacts[newPreviousContacts.length - 1],
+ };
+ this.setState({
+ contact: {
+ ID: currentParams.contactId,
+ title: currentParams.contactName,
+ sources: {
+ values: [
+ {
+ value: 'personal',
+ },
+ ],
+ },
+ seeker_path: 'none',
+ },
+ overallStatusBackgroundColor: '#ffffff',
+ });
+ navigation.setParams({
+ ...currentParams,
+ });
+ this.onRefresh(currentParams.contactId, true);
+ } else if (navigation.state.params.fromNotificationView) {
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'ContactList' })],
@@ -1165,36 +1257,23 @@ class ContactDetailScreen extends React.Component {
navigation.dispatch(resetAction);
navigation.navigate('NotificationList');
} else {
- navigation.goBack();
// Prevent error when view loaded from GroupDetailScreen.js
- if (typeof params.onGoBack === 'function') {
- params.onGoBack();
+ if (typeof navigation.state.params.onGoBack === 'function') {
+ navigation.state.params.onGoBack();
}
}
};
- onRefresh(contactId) {
- if (!self.state.loading) {
+ onRefresh(contactId, forceRefresh = false) {
+ if (!self.state.loading || forceRefresh) {
self.getContactById(contactId);
- self.onRefreshCommentsActivities(contactId);
+ self.onRefreshCommentsActivities(contactId, true);
}
}
- onRefreshCommentsActivities(contactId) {
- this.setState(
- {
- comments: [],
- activities: [],
- commentsOffset: 0,
- activitiesOffset: 0,
- },
- () => {
- this.getContactComments(contactId);
- if (this.props.isConnected) {
- this.getContactActivities(contactId);
- }
- },
- );
+ onRefreshCommentsActivities(contactId, resetPagination = false) {
+ this.getContactComments(contactId, resetPagination);
+ this.getContactActivities(contactId, resetPagination);
}
getLists = async (contactId) => {
@@ -1207,6 +1286,7 @@ class ContactDetailScreen extends React.Component {
users: JSON.parse(users).map((user) => ({
key: user.ID,
label: user.name,
+ contactID: parseInt(user.contact_id),
})),
};
}
@@ -1246,7 +1326,7 @@ class ContactDetailScreen extends React.Component {
})),
loadedLocal: true,
sources: [...sourcesList],
- unmodifiedSources: [...sourcesList]
+ unmodifiedSources: [...sourcesList],
};
this.setState(newState, () => {
@@ -1265,27 +1345,51 @@ class ContactDetailScreen extends React.Component {
this.props.getByIdEnd();
}
- getContactComments(contactId) {
- if (!this.state.loadComments) {
- this.props.getComments(
- this.props.userData.domain,
- this.props.userData.token,
- contactId,
- this.state.commentsOffset,
- this.state.commentsLimit,
- );
+ getContactComments(contactId, resetPagination = false) {
+ if (this.props.isConnected) {
+ if (resetPagination) {
+ this.props.getComments(this.props.userData.domain, this.props.userData.token, contactId, {
+ offset: 0,
+ limit: 10,
+ });
+ } else {
+ //ONLY GET DATA IF THERE IS MORE DATA TO GET
+ if (
+ !this.state.loadComments &&
+ this.state.comments.pagination.offset < this.state.comments.pagination.total
+ ) {
+ this.props.getComments(
+ this.props.userData.domain,
+ this.props.userData.token,
+ contactId,
+ this.state.comments.pagination,
+ );
+ }
+ }
}
}
- getContactActivities(contactId) {
- if (!this.state.loadActivities) {
- this.props.getActivities(
- this.props.userData.domain,
- this.props.userData.token,
- contactId,
- this.state.activitiesOffset,
- this.state.activitiesLimit,
- );
+ getContactActivities(contactId, resetPagination = false) {
+ if (this.props.isConnected) {
+ if (resetPagination) {
+ this.props.getActivities(this.props.userData.domain, this.props.userData.token, contactId, {
+ offset: 0,
+ limit: 10,
+ });
+ } else {
+ //ONLY GET DATA IF THERE IS MORE DATA TO GET
+ if (
+ !this.state.loadActivities &&
+ this.state.activities.pagination.offset < this.state.activities.pagination.total
+ ) {
+ this.props.getActivities(
+ this.props.userData.domain,
+ this.props.userData.token,
+ contactId,
+ this.state.activities.pagination,
+ );
+ }
+ }
}
}
@@ -1314,7 +1418,8 @@ class ContactDetailScreen extends React.Component {
};
onDisableEdit = () => {
- const { unmodifiedContact,
+ const {
+ unmodifiedContact,
unmodifiedSources,
unmodifiedSubAssignedContacts,
unmodifiedRelationContacts,
@@ -1323,11 +1428,14 @@ class ContactDetailScreen extends React.Component {
unmodifiedCoachedByContacts,
unmodifiedCoachedContacts,
unmodifiedConnectionGroups,
- unmodifedAssignedToContacts
+ unmodifedAssignedToContacts,
} = this.state;
this.setState((state) => {
+ // Set correct index in Tab position according to view mode and current tab position
const indexFix =
- state.tabViewConfig.index > 1 ? state.tabViewConfig.index + 1 : state.tabViewConfig.index;
+ state.tabViewConfig.index > 1 && !state.onlyView
+ ? state.tabViewConfig.index + 1
+ : state.tabViewConfig.index;
return {
onlyView: true,
contact: {
@@ -1349,7 +1457,7 @@ class ContactDetailScreen extends React.Component {
coachedByContacts: [...unmodifiedCoachedByContacts],
coachedContacts: [...unmodifiedCoachedContacts],
connectionGroups: [...unmodifiedConnectionGroups],
- assignedToContacts: [...unmodifedAssignedToContacts]
+ assignedToContacts: [...unmodifedAssignedToContacts],
};
});
this.props.navigation.setParams({ hideTabBar: false, onlyView: true });
@@ -1528,7 +1636,7 @@ class ContactDetailScreen extends React.Component {
ID: this.state.contact.ID,
};
}
- if(contactToSave.assigned_to) {
+ if (contactToSave.assigned_to) {
contactToSave = {
...contactToSave,
assigned_to: `user-${contactToSave.assigned_to.key}`,
@@ -1653,7 +1761,7 @@ class ContactDetailScreen extends React.Component {
getCommentsAndActivities() {
const { comments, activities } = this.state;
- const list = comments.concat(activities);
+ const list = comments.data.concat(activities.data);
return list
.filter((item, index) => list.indexOf(item) === index)
.sort((a, b) => new Date(a.date).getTime() < new Date(b.date).getTime());
@@ -1699,77 +1807,88 @@ class ContactDetailScreen extends React.Component {
);
- onBackFromSameScreen = () => {
- const { navigation } = this.props;
- const { params } = navigation.state;
- const newPreviousList = params.previousList;
- const previousParams = newPreviousList[newPreviousList.length - 1];
- newPreviousList.pop();
- navigation.setParams({
- ...previousParams,
- previousList: newPreviousList,
- });
- this.setState(initialState, () => {
- this.onLoad();
- });
- };
-
- goToContactDetailScreen = (contactID) => {
- const { navigation } = this.props;
+ goToContactDetailScreen = (contactID, name) => {
+ let { navigation } = this.props;
/* eslint-disable */
- const { params } = navigation.state;
- const { ID, title } = this.state.contact;
- params.previousList.push({
- contactId: ID,
- onlyView: true,
- contactName: title,
- });
+ // Save new contact in 'previousContacts' array
+ if (
+ !this.props.previousContacts.find(
+ (previousContact) => previousContact.contactId === contactID,
+ )
+ ) {
+ // Add contact to 'previousContacts' array on creation
+ this.props.updatePrevious([
+ ...this.props.previousContacts,
+ {
+ contactId: contactID,
+ onlyView: true,
+ contactName: name,
+ },
+ ]);
+ }
navigation.push('ContactDetail', {
- ...params, // previousList, onGoBack()
contactId: contactID,
onlyView: true,
- contactName: safeFind(
- this.state.usersContacts.find((user) => user.value === contactID),
- 'name',
- ),
- backButtonTap: this.backButtonTap.bind(this),
- onBackFromSameScreen: this.onBackFromSameScreen.bind(this),
+ contactName: name,
+ afterBack: () => this.afterBack(),
});
/* eslint-enable */
};
- goToGroupDetailScreen = (groupID) => {
+ goToGroupDetailScreen = (groupID, name) => {
+ // Clean 'previousContacts' array
+ this.props.updatePreviousGroups([
+ {
+ groupId: groupID,
+ onlyView: true,
+ groupName: name,
+ },
+ ]);
this.props.navigation.navigate('GroupDetail', {
groupId: groupID,
onlyView: true,
- groupName: safeFind(
- this.state.groups.find((groupItem) => groupItem.value === groupID),
- 'name',
- ),
- previousList: [],
+ groupName: name,
});
};
noCommentsRender = () => (
-
-
-
-
-
- {i18n.t('contactDetailScreen.noContactCommentPlacheHolder')}
-
-
- {i18n.t('contactDetailScreen.noContactCommentPlacheHolder1')}
-
- {!this.props.isConnected && (
-
- {i18n.t('contactDetailScreen.noContactCommentPlacheHolderOffline')}
-
- )}
-
+ this.onRefreshCommentsActivities(this.state.contact.ID, true)}
+ />
+ }>
+
+
+
+
+
+
+
+ {i18n.t('contactDetailScreen.noContactCommentPlacheHolder')}
+
+
+
+
+ {i18n.t('contactDetailScreen.noContactCommentPlacheHolder1')}
+
+
+ {!this.props.isConnected && (
+
+
+ {i18n.t('contactDetailScreen.noContactCommentPlacheHolderOffline')}
+
+
+ )}
+
+
+
);
detailView = () => (
+ /*_viewable_*/
{this.state.onlyView ? (
@@ -1780,16 +1899,27 @@ class ContactDetailScreen extends React.Component {
onRefresh={() => this.onRefresh(this.state.contact.ID)}
/>
}>
-
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+ {this.state.contact.assigned_to
+ ? this.renderContactLink(this.state.contact.assigned_to)
+ : null}
- {(this.state.contact.assigned_to) ? this.showAssignedUser() : null}
@@ -2034,18 +2177,18 @@ class ContactDetailScreen extends React.Component {
]}>
{this.state.contact.location_grid
? this.state.contact.location_grid.values
- .map(
- function (location) {
- return safeFind(
- this.state.geonames.find(
- (geoname) => geoname.value === location.value,
- ),
- 'name',
- );
- }.bind(this),
- )
- .filter(String)
- .join(', ')
+ .map(
+ function (location) {
+ return safeFind(
+ this.state.geonames.find(
+ (geoname) => geoname.value === location.value,
+ ),
+ 'name',
+ );
+ }.bind(this),
+ )
+ .filter(String)
+ .join(', ')
: ''}
@@ -2068,18 +2211,18 @@ class ContactDetailScreen extends React.Component {
]}>
{this.state.contact.people_groups
? this.state.contact.people_groups.values
- .map(
- function (peopleGroup) {
- return safeFind(
- this.state.peopleGroups.find(
- (person) => person.value === peopleGroup.value,
- ),
- 'name',
- );
- }.bind(this),
- )
- .filter(String)
- .join(', ')
+ .map(
+ function (peopleGroup) {
+ return safeFind(
+ this.state.peopleGroups.find(
+ (person) => person.value === peopleGroup.value,
+ ),
+ 'name',
+ );
+ }.bind(this),
+ )
+ .filter(String)
+ .join(', ')
: ''}
@@ -2092,7 +2235,11 @@ class ContactDetailScreen extends React.Component {
-
+
@@ -2126,7 +2273,7 @@ class ContactDetailScreen extends React.Component {
]}>
{this.state.contact.gender
? this.props.contactSettings.fields.gender.values[this.state.contact.gender]
- .label
+ .label
: ''}
@@ -2139,7 +2286,11 @@ class ContactDetailScreen extends React.Component {
-
+
{this.state.contact.sources
? `${this.state.contact.sources.values
- .map(
- (source) =>
- this.state.sources.find(
- (sourceItem) => sourceItem.value === source.value,
- ).name,
- )
- .join(', ')}`
+ .map(
+ (source) =>
+ this.state.sources.find(
+ (sourceItem) => sourceItem.value === source.value,
+ ).name,
+ )
+ .join(', ')}`
: ''}
@@ -2170,145 +2321,125 @@ class ContactDetailScreen extends React.Component {
) : (
-
-
-
- {this.props.contactSettings.fields.overall_status.name}
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
+
- {this.renderStatusPickerItems()}
-
-
-
-
-
-
-
-
-
-
-
- {i18n.t('contactDetailScreen.fullName.label')}
-
-
-
-
-
-
-
-
-
-
-
+ {this.renderStatusPickerItems()}
+
+
+
+
+
+
+
+
+
+
+
+ {i18n.t('contactDetailScreen.fullName.label')}
+
+
+
+
+
+
+
+
+
+
+
-
-
- {this.state.nameRequired ? (
-
- {i18n.t('contactDetailScreen.fullName.error')}
-
- ) : null}
+ : null
+ }>
+
-
- {
- this.updateShowAssignedToModal(true);
- }}>
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.assigned_to.name}
-
-
-
-
-
-
-
-
-
-
-
- {this.renderPickerItems([...this.state.users, ...this.state.assignedToContacts])}
-
-
-
-
+ {this.state.nameRequired ? (
+
+ {i18n.t('contactDetailScreen.fullName.error')}
+
+ ) : null}
+
+
+ {
+ this.updateShowAssignedToModal(true);
+ }}>
-
+
- {this.props.contactSettings.fields.subassigned.name}
+ {this.props.contactSettings.fields.assigned_to.name}
@@ -2316,573 +2447,630 @@ class ContactDetailScreen extends React.Component {
-
- {
- subAssignedSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.subAssignedContacts, ...this.state.usersContacts]}
- selectedItems={this.getSelectizeItems(
- this.state.contact.subassigned,
- [...this.state.subAssignedContacts, ...this.state.usersContacts],
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.subAssignThisContact'),
- }}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundSubassignedIndex = this.state.subAssignedContacts.findIndex(
- (subassigned) => subassigned.value === id
- );
- if (foundSubassignedIndex > -1) {
- // Remove subassigned from list
- const subAssignedContacts = [...this.state.subAssignedContacts];
- subAssignedContacts.splice(foundSubassignedIndex, 1);
- this.setState({
- subAssignedContacts: [...subAssignedContacts],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- renderRow={(id, onPress, item) => (
-
+
+ {this.renderPickerItems([
+ ...this.state.users,
+ ...this.state.assignedToContacts,
+ ])}
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.subassigned.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ subAssignedSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.subAssignedContacts, ...this.state.usersContacts]}
+ selectedItems={this.getSelectizeItems(this.state.contact.subassigned, [
+ ...this.state.subAssignedContacts,
+ ...this.state.usersContacts,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.subAssignThisContact'),
+ }}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundSubassignedIndex = this.state.subAssignedContacts.findIndex(
+ (subassigned) => subassigned.value === id,
+ );
+ if (foundSubassignedIndex > -1) {
+ // Remove subassigned from list
+ const subAssignedContacts = [...this.state.subAssignedContacts];
+ subAssignedContacts.splice(foundSubassignedIndex, 1);
+ this.setState({
+ subAssignedContacts: [...subAssignedContacts],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
+ />
+ )}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
- {i18n.t('contactDetailScreen.mobile')}
-
-
-
-
-
- {this.state.contact.contact_phone ? (
- this.state.contact.contact_phone.map((phone, index) =>
- !phone.delete ? (
-
-
-
-
-
-
-
- {
- this.onPhoneFieldChange(value, index, phone.key, this);
- }}
- style={styles.contactTextField}
- keyboardType="phone-pad"
- />
-
-
+
+
+ )}
+ filterOnKey="name"
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+
+
+
+
+
+ {i18n.t('contactDetailScreen.mobile')}
+
+
+
+
+
+ {this.state.contact.contact_phone ? (
+ this.state.contact.contact_phone.map((phone, index) =>
+ !phone.delete ? (
+
+
+
{
- this.onRemovePhoneField(index, this);
- }}
+ type="FontAwesome"
+ name="phone"
+ style={[styles.formIcon, { opacity: 0 }]}
/>
-
-
- ) : null,
- )
- ) : (
-
- )}
-
-
-
-
-
-
-
-
- {this.props.contactSettings.channels.email.label}
-
-
-
+
+
+
+ {
+ this.onPhoneFieldChange(value, index, phone.key, this);
+ }}
+ style={styles.contactTextField}
+ keyboardType="phone-pad"
+ />
+
+
+ {
+ this.onRemovePhoneField(index, this);
+ }}
+ />
+
+
+ ) : null,
+ )
+ ) : (
+
+ )}
+
+
+
-
-
- {this.state.contact.contact_email ? (
- this.state.contact.contact_email.map((email, index) =>
- !email.delete ? (
-
-
-
-
-
-
-
- {
- this.onEmailFieldChange(value, index, email.key, this);
- }}
- style={styles.contactTextField}
- keyboardType="email-address"
- />
-
-
+
+
+
+
+ {this.props.contactSettings.channels.email.label}
+
+
+
+
+
+
+ {this.state.contact.contact_email ? (
+ this.state.contact.contact_email.map((email, index) =>
+ !email.delete ? (
+
+
+
{
- this.onRemoveEmailField(index, this);
- }}
+ type="FontAwesome"
+ name="envelope"
+ style={[styles.formIcon, { opacity: 0 }]}
/>
-
-
- ) : null,
- )
- ) : (
-
- )}
-
-
-
-
-
-
-
- {i18n.t('contactDetailScreen.socialMedia')}
-
-
+
+
+
+ {
+ this.onEmailFieldChange(value, index, email.key, this);
+ }}
+ style={styles.contactTextField}
+ keyboardType="email-address"
+ />
+
+
+ {
+ this.onRemoveEmailField(index, this);
+ }}
+ />
+
+
+ ) : null,
+ )
+ ) : (
+
+ )}
+
+
+
-
-
- {Object.keys(this.props.contactSettings.channels)
- .filter(
- (channelName) =>
- channelName !== 'phone' && channelName !== 'email' && channelName !== 'address',
- )
- .map((channelName, channelNameIndex) => {
- const propertyName = `contact_${channelName}`;
- return (
-
- {this.state.contact[propertyName]
- ? this.state.contact[propertyName].map((socialMedia, socialMediaIndex) =>
+
+
+
+ {i18n.t('contactDetailScreen.socialMedia')}
+
+
+
+
+
+ {Object.keys(this.props.contactSettings.channels)
+ .filter(
+ (channelName) =>
+ channelName !== 'phone' && channelName !== 'email' && channelName !== 'address',
+ )
+ .map((channelName, channelNameIndex) => {
+ const propertyName = `contact_${channelName}`;
+ return (
+
+ {this.state.contact[propertyName]
+ ? this.state.contact[propertyName].map((socialMedia, socialMediaIndex) =>
!socialMedia.key
? this.renderSocialMediaField(
- socialMediaIndex,
- socialMedia,
- propertyName,
- channelName,
- )
+ socialMediaIndex,
+ socialMedia,
+ propertyName,
+ channelName,
+ )
: null,
)
- : null}
-
- );
- })}
- {Object.keys(this.props.contactSettings.channels)
- .filter(
- (channelName) =>
- channelName !== 'phone' && channelName !== 'email' && channelName !== 'address',
- )
- .map((channelName, channelNameIndex) => {
- const propertyName = `contact_${channelName}`;
- return (
-
- {this.state.contact[propertyName]
- ? this.state.contact[propertyName].map((socialMedia, socialMediaIndex) =>
+ : null}
+
+ );
+ })}
+ {Object.keys(this.props.contactSettings.channels)
+ .filter(
+ (channelName) =>
+ channelName !== 'phone' && channelName !== 'email' && channelName !== 'address',
+ )
+ .map((channelName, channelNameIndex) => {
+ const propertyName = `contact_${channelName}`;
+ return (
+
+ {this.state.contact[propertyName]
+ ? this.state.contact[propertyName].map((socialMedia, socialMediaIndex) =>
socialMedia.key && !socialMedia.delete
? this.renderSocialMediaField(
- socialMediaIndex,
- socialMedia,
- propertyName,
- channelName,
- )
+ socialMediaIndex,
+ socialMedia,
+ propertyName,
+ channelName,
+ )
: null,
)
- : null}
+ : null}
+
+ );
+ })}
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.channels.address.label}
+
+
+
+
+
+
+ {this.state.contact.contact_address ? (
+ this.state.contact.contact_address.map((address, index) =>
+ !address.delete ? (
+
+
+
+
+
- );
- })}
-
-
-
-
-
-
-
-
- {this.props.contactSettings.channels.address.label}
-
-
-
+
+ {
+ this.onAddressFieldChange(value, index, address.key, this);
+ }}
+ style={styles.contactTextField}
+ />
+
+
+ {
+ this.onRemoveAddressField(index, this);
+ }}
+ />
+
+
+ ) : null,
+ )
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.location_grid.name}
+
+
+
+
+
+
-
-
- {this.state.contact.contact_address ? (
- this.state.contact.contact_address.map((address, index) =>
- !address.delete ? (
-
-
-
-
-
-
-
- {
- this.onAddressFieldChange(value, index, address.key, this);
- }}
- style={styles.contactTextField}
- />
-
-
- {
- this.onRemoveAddressField(index, this);
- }}
- />
-
-
- ) : null,
- )
- ) : (
-
- )}
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.location_grid.name}
-
-
-
-
-
-
-
+
+
+ {
+ geonamesSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={this.state.foundGeonames}
+ selectedItems={this.getSelectizeItems(
+ this.state.contact.location_grid,
+ this.state.geonames,
+ )}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.selectLocations'),
+ }}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+
-
-
-
- {
- geonamesSelectizeRef = selectize;
- }}
- itemId="value"
- items={this.state.foundGeonames}
- selectedItems={this.getSelectizeItems(
- this.state.contact.location_grid,
- this.state.geonames,
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.selectLocations'),
- }}
- renderChip={(id, onClose, item, style, iconStyle) => (
-
- )}
- renderRow={(id, onPress, item) => (
- (
+
+
-
-
- {item.name}
-
-
-
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- textInputProps={{
- onChangeText: this.searchLocationsDelayed,
- }}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.people_groups.name}
-
-
-
-
-
-
-
-
-
-
- {
- peopleGroupsSelectizeRef = selectize;
- }}
- itemId="value"
- items={this.state.peopleGroups}
- selectedItems={this.getSelectizeItems(
- this.state.contact.people_groups,
- this.state.peopleGroups,
- )}
- textInputProps={{
- placeholder: i18n.t('global.selectPeopleGroups'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+ )}
+ filterOnKey="name"
+ inputContainerStyle={styles.selectizeField}
+ textInputProps={{
+ onChangeText: this.searchLocationsDelayed,
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.people_groups.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ peopleGroupsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={this.state.peopleGroups}
+ selectedItems={this.getSelectizeItems(
+ this.state.contact.people_groups,
+ this.state.peopleGroups,
+ )}
+ textInputProps={{
+ placeholder: i18n.t('global.selectPeopleGroups'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
-
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.age.name}
-
-
-
-
-
-
-
-
-
-
- {Object.keys(this.props.contactSettings.fields.age.values).map((key) => {
- const optionData = this.props.contactSettings.fields.age.values[key];
- return ;
- })}
-
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.gender.name}
-
-
-
-
-
-
-
-
-
-
-
- {Object.keys(this.props.contactSettings.fields.gender.values).map((key) => {
- const optionData = this.props.contactSettings.fields.gender.values[key];
- return ;
- })}
-
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.sources.name}
-
-
-
-
-
-
-
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+
-
-
-
- {
- sourcesSelectizeRef = selectize;
- }}
- itemId="value"
- items={this.state.sources}
- selectedItems={
- this.state.contact.sources
- ? // Only add option elements (by contact sources) does exist in source list
+ )}
+ filterOnKey="name"
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.age.name}
+
+
+
+
+
+
+
+
+
+
+ {Object.keys(this.props.contactSettings.fields.age.values).map((key) => {
+ const optionData = this.props.contactSettings.fields.age.values[key];
+ return ;
+ })}
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.gender.name}
+
+
+
+
+
+
+
+
+
+
+
+ {Object.keys(this.props.contactSettings.fields.gender.values).map((key) => {
+ const optionData = this.props.contactSettings.fields.gender.values[key];
+ return ;
+ })}
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.sources.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ sourcesSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={this.state.sources}
+ selectedItems={
+ this.state.contact.sources
+ ? // Only add option elements (by contact sources) does exist in source list
this.state.contact.sources.values
.filter((contactSource) =>
this.state.sources.find(
@@ -2897,73 +3085,74 @@ class ContactDetailScreen extends React.Component {
value: contactSource.value,
};
})
- : []
- }
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.selectSources'),
- }}
- renderRow={(id, onPress, item) => (
- (
+
+
-
-
- {item.name}
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- const nonExistingSourcesList = [...this.state.nonExistingSources];
- let foundNonExistingSource = nonExistingSourcesList.findIndex(
- (source) => source.value === id,
- );
- if (foundNonExistingSource > -1) {
- // Remove custom source from select list
- const sourceList = [...this.state.sources]; //,
- let foundSourceIndex = sourceList.findIndex(
- (source) => source.value === id,
- );
- sourceList.splice(foundSourceIndex, 1);
- this.setState({
- sources: [...sourceList],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
- )}
+ color: 'rgba(0, 0, 0, 0.87)',
+ fontSize: 14,
+ lineHeight: 21,
+ }}>
+ {item.name}
+
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ const nonExistingSourcesList = [...this.state.nonExistingSources];
+ let foundNonExistingSource = nonExistingSourcesList.findIndex(
+ (source) => source.value === id,
+ );
+ if (foundNonExistingSource > -1) {
+ // Remove custom source from select list
+ const sourceList = [...this.state.sources]; //,
+ let foundSourceIndex = sourceList.findIndex(
+ (source) => source.value === id,
+ );
+ sourceList.splice(foundSourceIndex, 1);
+ this.setState({
+ sources: [...sourceList],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
+ />
+ )}
+ filterOnKey="name"
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+ )}
);
progressView = () => (
+ /*_viewable_*/
{this.state.onlyView ? (
@@ -2974,8 +3163,8 @@ class ContactDetailScreen extends React.Component {
onRefresh={() => this.onRefresh(this.state.contact.ID)}
/>
}>
-
-
+
+
{this.state.contact.seeker_path
? this.props.contactSettings.fields.seeker_path.values[
- this.state.contact.seeker_path
- ].label
+ this.state.contact.seeker_path
+ ].label
: ''}
@@ -3015,14 +3204,21 @@ class ContactDetailScreen extends React.Component {
/>
-
- {this.props.contactSettings.fields.milestones.name}
-
+
+
+
+
+
+
+ {this.props.contactSettings.fields.milestones.name}
+
+
+
{this.renderfaithMilestones()}
{this.renderCustomFaithMilestones()}
@@ -3034,7 +3230,9 @@ class ContactDetailScreen extends React.Component {
{this.state.contact.baptism_date
- ? moment(new Date(this.state.contact.baptism_date * 1000)).format('LL')
+ ? moment(new Date(this.state.contact.baptism_date * 1000))
+ .utc()
+ .format('LL')
: ''}
@@ -3049,90 +3247,100 @@ class ContactDetailScreen extends React.Component {
) : (
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.seeker_path.name}
-
-
-
-
-
-
-
-
-
-
-
- {Object.keys(this.props.contactSettings.fields.seeker_path.values).map((key) => {
- const optionData = this.props.contactSettings.fields.seeker_path.values[key];
- return ;
- })}
-
-
-
-
- {this.props.contactSettings.fields.milestones.name}
-
- {this.renderfaithMilestones()}
- {this.renderCustomFaithMilestones()}
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.baptism_date.name}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
- )}
+
+
+
+
+ {this.props.contactSettings.fields.seeker_path.name}
+
+
+
+
+
+
+
+
+
+
+
+ {Object.keys(this.props.contactSettings.fields.seeker_path.values).map((key) => {
+ const optionData = this.props.contactSettings.fields.seeker_path.values[key];
+ return ;
+ })}
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.milestones.name}
+
+
+
+ {this.renderfaithMilestones()}
+ {this.renderCustomFaithMilestones()}
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.baptism_date.name}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
);
@@ -3177,78 +3385,63 @@ class ContactDetailScreen extends React.Component {
}
commentsView = () => (
+ /*_viewable_*/
- {this.state.comments.length == 0 &&
- this.state.activities.length == 0 &&
- !this.state.loadComments &&
- !this.state.loadActivities &&
- this.noCommentsRender()}
- {
- commentsFlatList = flatList;
- }}
- data={this.getCommentsAndActivities()}
- extraData={!this.state.loadingMoreComments || !this.state.loadingMoreActivities}
- inverted
- ItemSeparatorComponent={() => (
-
- )}
- keyExtractor={(item, index) => String(index)}
- renderItem={(item) => {
- const commentOrActivity = item.item;
- return this.renderActivityOrCommentRow(commentOrActivity);
- }}
- refreshControl={
- this.onRefreshCommentsActivities(this.state.contact.ID)}
- />
- }
- onScroll={({ nativeEvent }) => {
- const { loadingMoreComments, commentsOffset, activitiesOffset } = this.state;
- const flatList = nativeEvent;
- const contentOffsetY = flatList.contentOffset.y;
- const layoutMeasurementHeight = flatList.layoutMeasurement.height;
- const contentSizeHeight = flatList.contentSize.height;
- const heightOffsetSum = layoutMeasurementHeight + contentOffsetY;
- const distanceToStart = contentSizeHeight - heightOffsetSum;
-
- if (distanceToStart < 100) {
- if (!loadingMoreComments) {
- if (commentsOffset < this.state.totalComments) {
- this.setState(
- {
- loadingMoreComments: true,
- },
- () => {
- this.getContactComments(this.state.contact.ID);
- },
- );
- }
- }
- if (!this.state.loadingMoreActivities) {
- if (activitiesOffset < this.state.totalActivities) {
- this.setState(
- {
- loadingMoreActivities: true,
- },
- () => {
- this.getContactActivities(this.state.contact.ID);
- },
- );
- }
- }
+ {this.state.comments.data.length == 0 &&
+ this.state.activities.data.length == 0 &&
+ !this.state.loadComments &&
+ !this.state.loadActivities ? (
+ this.noCommentsRender()
+ ) : (
+ {
+ commentsFlatList = flatList;
+ }}
+ data={this.getCommentsAndActivities()}
+ extraData={!this.state.loadingMoreComments || !this.state.loadingMoreActivities}
+ inverted
+ ItemSeparatorComponent={() => (
+
+ )}
+ keyExtractor={(item, index) => String(index)}
+ renderItem={(item) => {
+ const commentOrActivity = item.item;
+ return this.renderActivityOrCommentRow(commentOrActivity);
+ }}
+ refreshControl={
+ this.onRefreshCommentsActivities(this.state.contact.ID, true)}
+ />
}
- }}
- />
+ onScroll={({ nativeEvent }) => {
+ sharedTools.onlyExecuteLastCall(
+ {},
+ () => {
+ const flatList = nativeEvent;
+ const contentOffsetY = flatList.contentOffset.y;
+ const layoutMeasurementHeight = flatList.layoutMeasurement.height;
+ const contentSizeHeight = flatList.contentSize.height;
+ const heightOffsetSum = layoutMeasurementHeight + contentOffsetY;
+ const distanceToStart = contentSizeHeight - heightOffsetSum;
+ if (distanceToStart < 100) {
+ this.getContactComments(this.state.contact.ID);
+ this.getContactActivities(this.state.contact.ID);
+ }
+ },
+ 500,
+ );
+ }}
+ />
+ )}
(
+ /*_viewable_*/
{this.state.onlyView ? (
@@ -3325,7 +3519,7 @@ class ContactDetailScreen extends React.Component {
onRefresh={() => this.onRefresh(this.state.contact.ID)}
/>
}>
-
+
-
+
{this.state.contact.groups ? (
- this.state.contact.groups.values.map((group, index) =>
+ this.state.contact.groups.values.map((group, index) => (
this.goToGroupDetailScreen(group.value)}>
-
+ onPress={() => this.goToGroupDetailScreen(group.value, group.name)}>
+
{group.name}
- )) : (
-
- )}
+ ))
+ ) : (
+
+ )}
@@ -3364,27 +3560,33 @@ class ContactDetailScreen extends React.Component {
-
+
-
+
{this.state.contact.relation ? (
- this.state.contact.relation.values.map((contact, index) =>
+ this.state.contact.relation.values.map((contact, index) => (
this.goToContactDetailScreen(contact.value)}>
-
+ onPress={() => this.goToContactDetailScreen(contact.value, contact.name)}>
+
{contact.name}
- )) : (
-
- )}
+ ))
+ ) : (
+
+ )}
@@ -3399,24 +3601,26 @@ class ContactDetailScreen extends React.Component {
-
+
{this.state.contact.baptized_by ? (
- this.state.contact.baptized_by.values.map((contact, index) =>
+ this.state.contact.baptized_by.values.map((contact, index) => (
this.goToContactDetailScreen(contact.value)}>
-
+ onPress={() => this.goToContactDetailScreen(contact.value, contact.name)}>
+
{contact.name}
- )) : (
-
- )}
+ ))
+ ) : (
+
+ )}
@@ -3435,24 +3639,26 @@ class ContactDetailScreen extends React.Component {
/>
-
+
{this.state.contact.baptized ? (
- this.state.contact.baptized.values.map((contact, index) =>
+ this.state.contact.baptized.values.map((contact, index) => (
this.goToContactDetailScreen(contact.value)}>
-
+ onPress={() => this.goToContactDetailScreen(contact.value, contact.name)}>
+
{contact.name}
- )) : (
-
- )}
+ ))
+ ) : (
+
+ )}
@@ -3471,24 +3677,26 @@ class ContactDetailScreen extends React.Component {
/>
-
+
{this.state.contact.coached_by ? (
- this.state.contact.coached_by.values.map((contact, index) =>
+ this.state.contact.coached_by.values.map((contact, index) => (
this.goToContactDetailScreen(contact.value)}>
-
+ onPress={() => this.goToContactDetailScreen(contact.value, contact.name)}>
+
{contact.name}
- )) : (
-
- )}
+ ))
+ ) : (
+
+ )}
@@ -3507,24 +3715,26 @@ class ContactDetailScreen extends React.Component {
/>
-
+
{this.state.contact.coaching ? (
- this.state.contact.coaching.values.map((contact, index) =>
+ this.state.contact.coaching.values.map((contact, index) => (
this.goToContactDetailScreen(contact.value)}>
-
+ onPress={() => this.goToContactDetailScreen(contact.value, contact.name)}>
+
{contact.name}
- )) : (
-
- )}
+ ))
+ ) : (
+
+ )}
@@ -3538,598 +3748,598 @@ class ContactDetailScreen extends React.Component {
) : (
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.groups.name}
-
-
-
-
-
-
-
-
-
-
- {
- groupsSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.connectionGroups, ...this.state.groups]}
- selectedItems={this.getSelectizeItems(
- this.state.contact.groups,
- [...this.state.connectionGroups, ...this.state.groups],
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.addGroup'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.groups.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ groupsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.connectionGroups, ...this.state.groups]}
+ selectedItems={this.getSelectizeItems(this.state.contact.groups, [
+ ...this.state.connectionGroups,
+ ...this.state.groups,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.addGroup'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundGroupIndex = this.state.connectionGroups.findIndex(
- (groupConnection) => groupConnection.value === id
- );
- if (foundGroupIndex > -1) {
- // Remove group from list
- const connectionGroups = [...this.state.connectionGroups];
- connectionGroups.splice(foundGroupIndex, 1);
- this.setState({
- connectionGroups: [...connectionGroups],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.relation.name}
-
-
-
-
-
-
-
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundGroupIndex = this.state.connectionGroups.findIndex(
+ (groupConnection) => groupConnection.value === id,
+ );
+ if (foundGroupIndex > -1) {
+ // Remove group from list
+ const connectionGroups = [...this.state.connectionGroups];
+ connectionGroups.splice(foundGroupIndex, 1);
+ this.setState({
+ connectionGroups: [...connectionGroups],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
/>
-
-
-
- {
- connectionsSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.relationContacts, ...this.state.usersContacts]}
- selectedItems={this.getSelectizeItems(
- this.state.contact.relation,
- [...this.state.relationContacts, ...this.state.usersContacts],
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.addConnection'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.relation.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ connectionsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.relationContacts, ...this.state.usersContacts]}
+ selectedItems={this.getSelectizeItems(this.state.contact.relation, [
+ ...this.state.relationContacts,
+ ...this.state.usersContacts,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.addConnection'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundRelationIndex = this.state.relationContacts.findIndex(
- (relation) => relation.value === id
- );
- if (foundRelationIndex > -1) {
- // Remove relation from list
- const relationContacts = [...this.state.relationContacts];
- relationContacts.splice(foundRelationIndex, 1);
- this.setState({
- relationContacts: [...relationContacts],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.baptized_by.name}
-
-
-
-
-
-
-
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundRelationIndex = this.state.relationContacts.findIndex(
+ (relation) => relation.value === id,
+ );
+ if (foundRelationIndex > -1) {
+ // Remove relation from list
+ const relationContacts = [...this.state.relationContacts];
+ relationContacts.splice(foundRelationIndex, 1);
+ this.setState({
+ relationContacts: [...relationContacts],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
/>
-
-
-
- {
- baptizedBySelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.baptizedByContacts, ...this.state.usersContacts]}
- selectedItems={this.getSelectizeItems(
- this.state.contact.baptized_by,
- [...this.state.baptizedByContacts, ...this.state.usersContacts],
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.addBaptizedBy'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.baptized_by.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ baptizedBySelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.baptizedByContacts, ...this.state.usersContacts]}
+ selectedItems={this.getSelectizeItems(this.state.contact.baptized_by, [
+ ...this.state.baptizedByContacts,
+ ...this.state.usersContacts,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.addBaptizedBy'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundBaptizedByIndex = this.state.baptizedByContacts.findIndex(
- (baptized) => baptized.value === id
- );
- if (foundBaptizedByIndex > -1) {
- // Remove baptized from list
- const baptizedByContacts = [...this.state.baptizedByContacts];
- baptizedByContacts.splice(foundBaptizedByIndex, 1);
- this.setState({
- baptizedByContacts: [...baptizedByContacts],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.baptized.name}
-
-
-
-
-
-
-
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundBaptizedByIndex = this.state.baptizedByContacts.findIndex(
+ (baptized) => baptized.value === id,
+ );
+ if (foundBaptizedByIndex > -1) {
+ // Remove baptized from list
+ const baptizedByContacts = [...this.state.baptizedByContacts];
+ baptizedByContacts.splice(foundBaptizedByIndex, 1);
+ this.setState({
+ baptizedByContacts: [...baptizedByContacts],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
/>
-
-
-
- {
- baptizedSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.baptizedContacts, ...this.state.usersContacts]}
- selectedItems={this.getSelectizeItems(
- this.state.contact.baptized,
- [...this.state.baptizedContacts, ...this.state.usersContacts],
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.addBaptized'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.baptized.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ baptizedSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.baptizedContacts, ...this.state.usersContacts]}
+ selectedItems={this.getSelectizeItems(this.state.contact.baptized, [
+ ...this.state.baptizedContacts,
+ ...this.state.usersContacts,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.addBaptized'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundBaptizedIndex = this.state.baptizedContacts.findIndex(
- (baptized) => baptized.value === id
- );
- if (foundBaptizedIndex > -1) {
- // Remove baptized from list
- const baptizedContacts = [...this.state.baptizedContacts];
- baptizedContacts.splice(foundBaptizedIndex, 1);
- this.setState({
- baptizedContacts: [...baptizedContacts],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.coached_by.name}
-
-
-
-
-
-
-
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundBaptizedIndex = this.state.baptizedContacts.findIndex(
+ (baptized) => baptized.value === id,
+ );
+ if (foundBaptizedIndex > -1) {
+ // Remove baptized from list
+ const baptizedContacts = [...this.state.baptizedContacts];
+ baptizedContacts.splice(foundBaptizedIndex, 1);
+ this.setState({
+ baptizedContacts: [...baptizedContacts],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
/>
-
-
-
- {
- coachedSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.coachedByContacts, ...this.state.usersContacts]}
- selectedItems={this.getSelectizeItems(
- this.state.contact.coached_by,
- [...this.state.coachedByContacts, ...this.state.usersContacts],
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.addCoachedBy'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.coached_by.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ coachedSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.coachedByContacts, ...this.state.usersContacts]}
+ selectedItems={this.getSelectizeItems(this.state.contact.coached_by, [
+ ...this.state.coachedByContacts,
+ ...this.state.usersContacts,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.addCoachedBy'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundCoachedByIndex = this.state.coachedByContacts.findIndex(
- (coachedBy) => coachedBy.value === id
- );
- if (foundCoachedByIndex > -1) {
- // Remove coachedBy from list
- const coachedByContacts = [...this.state.coachedByContacts];
- coachedByContacts.splice(foundCoachedByIndex, 1);
- this.setState({
- coachedByContacts: [...coachedByContacts],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.coaching.name}
-
-
-
-
-
-
-
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundCoachedByIndex = this.state.coachedByContacts.findIndex(
+ (coachedBy) => coachedBy.value === id,
+ );
+ if (foundCoachedByIndex > -1) {
+ // Remove coachedBy from list
+ const coachedByContacts = [...this.state.coachedByContacts];
+ coachedByContacts.splice(foundCoachedByIndex, 1);
+ this.setState({
+ coachedByContacts: [...coachedByContacts],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
/>
-
-
-
- {
- coachingSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.coachedContacts, ...this.state.usersContacts]}
- selectedItems={this.getSelectizeItems(
- this.state.contact.coaching,
- [...this.state.coachedContacts, ...this.state.usersContacts],
- )}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.addCoaching'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.coaching.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ coachingSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.coachedContacts, ...this.state.usersContacts]}
+ selectedItems={this.getSelectizeItems(this.state.contact.coaching, [
+ ...this.state.coachedContacts,
+ ...this.state.usersContacts,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.addCoaching'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundCoachedIndex = this.state.coachedContacts.findIndex(
- (coached) => coached.value === id
- );
- if (foundCoachedIndex > -1) {
- // Remove coached from list
- const coachedContacts = [...this.state.coachedContacts];
- coachedContacts.splice(foundCoachedIndex, 1);
- this.setState({
- coachedContacts: [...coachedContacts],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
- )}
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundCoachedIndex = this.state.coachedContacts.findIndex(
+ (coached) => coached.value === id,
+ );
+ if (foundCoachedIndex > -1) {
+ // Remove coached from list
+ const coachedContacts = [...this.state.coachedContacts];
+ coachedContacts.splice(foundCoachedIndex, 1);
+ this.setState({
+ coachedContacts: [...coachedContacts],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
+ />
+ )}
+ filterOnKey="name"
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+ )}
);
@@ -4264,6 +4474,16 @@ class ContactDetailScreen extends React.Component {
return transformedContact;
};
+ openCommentDialog = (comment, deleteComment = false) => {
+ this.setState({
+ commentDialog: {
+ toggle: true,
+ data: comment,
+ delete: deleteComment,
+ },
+ });
+ };
+
renderActivityOrCommentRow = (commentOrActivity) => (
+ {
+ // Comment and its their own comment
+ Object.prototype.hasOwnProperty.call(commentOrActivity, 'content') &&
+ commentOrActivity.author.toLowerCase() ===
+ this.props.userData.username.toLowerCase() && (
+
+
+ {
+ this.openCommentDialog(commentOrActivity, true);
+ }}>
+
+
+ {i18n.t('global.delete')}
+
+
+ {
+ this.openCommentDialog(commentOrActivity);
+ }}>
+
+
+ {i18n.t('global.edit')}
+
+
+
+
+ )
+ }
);
@@ -4394,7 +4675,6 @@ class ContactDetailScreen extends React.Component {
...prevState.tabViewConfig,
index,
},
- renderFab: !(index === 2),
}));
};
@@ -4594,11 +4874,11 @@ class ContactDetailScreen extends React.Component {
key: value,
label: [...this.state.users, ...this.state.assignedToContacts].find(
(user) => user.key === value,
- ).label
+ ).label,
},
},
showAssignedToModal: false,
- assignedToContacts: [] // Clear non existing assigentToContacts list
+ assignedToContacts: [], // Clear non existing assigentToContacts list
}));
};
@@ -4608,19 +4888,60 @@ class ContactDetailScreen extends React.Component {
});
};
- showAssignedUser = () => {
- const foundUser = [...this.state.users, ...this.state.assignedToContacts].find(
- (user) => user.key === this.state.contact.assigned_to.key,
- );
- return (
-
- {foundUser.label}
-
+ renderContactLink = (assignedTo) => {
+ let foundContact, valueToSearch, nameToShow;
+ if (assignedTo.key) {
+ valueToSearch = assignedTo.key;
+ nameToShow = assignedTo.label;
+ } else if (assignedTo.value) {
+ valueToSearch = assignedTo.value;
+ nameToShow = assignedTo.name;
+ }
+ foundContact = this.state.users.find(
+ (user) => user.key === parseInt(valueToSearch) || user.contactID === parseInt(valueToSearch),
);
+ if (!foundContact) {
+ foundContact = this.state.usersContacts.find(
+ (user) => user.value === valueToSearch.toString(),
+ );
+ }
+ // User have accesss to this assigned_to user/contact
+ if (foundContact && foundContact.contactID) {
+ // Contact exist in 'this.state.users' list
+ return (
+ this.goToContactDetailScreen(foundContact.contactID, nameToShow)}>
+
+ {nameToShow}
+
+
+ );
+ } else if (foundContact) {
+ // Contact exist in 'this.state.usersContacts' list
+ return (
+ this.goToContactDetailScreen(valueToSearch, nameToShow)}>
+
+ {nameToShow}
+
+
+ );
+ } else {
+ // User does not exist in any list
+ return (
+
+ {nameToShow}
+
+ );
+ }
};
socialMediaKeyIsDB = (key) => key;
@@ -4711,6 +5032,36 @@ class ContactDetailScreen extends React.Component {
}));
};
+ onCloseCommentDialog() {
+ this.setState({
+ commentDialog: {
+ toggle: false,
+ data: {},
+ delete: false,
+ },
+ });
+ }
+
+ onUpdateComment(commentData) {
+ this.props.saveComment(
+ this.props.userData.domain,
+ this.props.userData.token,
+ this.state.contact.ID,
+ commentData,
+ );
+ this.onCloseCommentDialog();
+ }
+
+ onDeleteComment(commentData) {
+ this.props.deleteComment(
+ this.props.userData.domain,
+ this.props.userData.token,
+ this.state.contact.ID,
+ commentData.ID,
+ );
+ this.onCloseCommentDialog();
+ }
+
renderfaithMilestones() {
return (
{
this.onRemoveSocialMediaField(propertyName, socialMediaIndex, this);
}}
@@ -5204,23 +5555,35 @@ class ContactDetailScreen extends React.Component {
this.props.searchLocations(this.props.userData.domain, this.props.userData.token, queryText);
};
- onMeetingComplete = (props) => {
- /*
- if (true) {
- this.props.navigation.navigate(NavigationActions.navigate({
- routeName: 'Questionnaire',
- action: NavigationActions.navigate({
- routeName: 'Question', params: {
- userData: this.state.userData,
- contact: this.state.contact,
- },
- })
- }));
- } else {
- this.onSaveQuickAction('quick_button_meeting_complete');
- }
- */
+ onMeetingComplete = () => {
this.onSaveQuickAction('quick_button_meeting_complete');
+ var isQuestionnaireEnabled = false;
+ var q_id = null;
+ // loop thru all (active) questionnaires, and check whether 'contact'->'meeting_complete' is enabled
+ this.props.questionnaires.map((questionnaire) => {
+ if (
+ questionnaire.trigger_type == 'contact' &&
+ questionnaire.trigger_value == 'meeting_complete'
+ ) {
+ isQuestionnaireEnabled = true;
+ q_id = questionnaire.id;
+ }
+ });
+ if (isQuestionnaireEnabled) {
+ this.props.navigation.navigate(
+ NavigationActions.navigate({
+ routeName: 'Questionnaire',
+ action: NavigationActions.navigate({
+ routeName: 'Question',
+ params: {
+ userData: this.props.userData,
+ contact: this.state.contact,
+ q_id,
+ },
+ }),
+ }),
+ );
+ }
};
onSaveQuickAction = (quickActionPropertyName) => {
@@ -5335,7 +5698,7 @@ class ContactDetailScreen extends React.Component {
onIndexChange={this.tabChanged}
initialLayout={{ width: windowWidth }}
/>
- {this.state.renderFab && (
+ {this.state.onlyView && this.state.tabViewConfig.index != 2 && (
@@ -5346,31 +5709,30 @@ class ContactDetailScreen extends React.Component {
style={{ color: 'white', fontSize: 22 }}
/>
) : (
-
- )
+
+ )
}
degrees={0}
activeOpacity={0}
bgColor="rgba(0,0,0,0.5)"
nativeFeedbackRippleColor="rgba(0,0,0,0)">
{
this.onSaveQuickAction('quick_button_no_answer');
}}
size={40}
+ buttonColor={Colors.colorNo}
nativeFeedbackRippleColor="rgba(0,0,0,0)"
textStyle={{ color: Colors.tintColor, fontSize: 15 }}
textContainerStyle={{ height: 'auto' }}>
@@ -5388,13 +5751,13 @@ class ContactDetailScreen extends React.Component {
/>
{
this.onSaveQuickAction('quick_button_meeting_scheduled');
}}
+ buttonColor={Colors.colorWait}
size={40}
nativeFeedbackRippleColor="rgba(0,0,0,0)"
textStyle={{ color: Colors.tintColor, fontSize: 15 }}
@@ -5406,12 +5769,12 @@ class ContactDetailScreen extends React.Component {
/>
{
- this.onMeetingComplete(this.props);
+ this.onMeetingComplete();
}}
size={40}
+ buttonColor={Colors.colorYes}
nativeFeedbackRippleColor="rgba(0,0,0,0)"
textStyle={{ color: Colors.tintColor, fontSize: 15 }}
textContainerStyle={{ height: 'auto' }}>
@@ -5422,12 +5785,12 @@ class ContactDetailScreen extends React.Component {
/>
{
this.onSaveQuickAction('quick_button_no_show');
}}
size={40}
+ buttonColor={Colors.colorNo}
nativeFeedbackRippleColor="rgba(0,0,0,0)"
textStyle={{ color: Colors.tintColor, fontSize: 15 }}
textContainerStyle={{ height: 'auto' }}>
@@ -5439,468 +5802,642 @@ class ContactDetailScreen extends React.Component {
)}
+ {this.state.commentDialog.toggle ? (
+
+
+
+
+
+ {this.state.commentDialog.delete ? (
+
+
+
+ {i18n.t('global.delete')}
+
+
+
+
+ {this.state.commentDialog.data.content}
+
+
+
+ ) : (
+
+
+
+
+ {i18n.t('global.edit')}
+
+
+
+ {
+ this.setState((prevState) => ({
+ commentDialog: {
+ ...prevState.commentDialog,
+ data: {
+ ...prevState.commentDialog.data,
+ content: value,
+ },
+ },
+ }));
+ }}
+ style={[
+ styles.contactTextField,
+ { height: 'auto', minHeight: 50 },
+ ]}
+ />
+
+
+
+ )}
+
+
+
+ {this.state.commentDialog.delete ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ ) : null}
) : (
-
- {!this.props.isConnected && this.offlineBarRender()}
-
-
-
-
+
+ {!this.props.isConnected && this.offlineBarRender()}
+
+
+
+
+
+
+
+
+
+
{i18n.t('contactDetailScreen.fullName.label')}
-
-
+
+
-
-
- {this.state.nameRequired ? (
-
- {i18n.t('contactDetailScreen.fullName.error')}
-
- ) : null}
-
-
+ : null
+ }>
+
+
+ {this.state.nameRequired ? (
+
+ {i18n.t('contactDetailScreen.fullName.error')}
+
+ ) : null}
+
+
+
+
+
+
+
+
{i18n.t('contactDetailScreen.phoneNumber')}
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
{this.props.contactSettings.channels.email.label}
-
-
-
-
-
-
-
-
-
-
-
-
- {i18n.t('contactDetailScreen.socialMedia')}
-
-
-
+
+
+
+
+
+
+
+
-
-
- {Object.keys(this.props.contactSettings.channels)
- .filter(
- (channelName) =>
- channelName !== 'phone' &&
- channelName !== 'email' &&
- channelName !== 'address',
- )
- .map((channelName, channelNameIndex) => {
- const propertyName = `contact_${channelName}`;
- return (
-
- {this.state.contact[propertyName]
- ? this.state.contact[
+
+
+
+
+ {i18n.t('contactDetailScreen.socialMedia')}
+
+
+
+
+
+
+ {Object.keys(this.props.contactSettings.channels)
+ .filter(
+ (channelName) =>
+ channelName !== 'phone' &&
+ channelName !== 'email' &&
+ channelName !== 'address',
+ )
+ .map((channelName, channelNameIndex) => {
+ const propertyName = `contact_${channelName}`;
+ return (
+
+ {this.state.contact[propertyName]
+ ? this.state.contact[
propertyName
].map((socialMedia, socialMediaIndex) =>
!socialMedia.key
? this.renderSocialMediaField(
- socialMediaIndex,
- socialMedia,
- propertyName,
- channelName,
- )
+ socialMediaIndex,
+ socialMedia,
+ propertyName,
+ channelName,
+ )
: null,
)
- : null}
-
- );
- })}
- {Object.keys(this.props.contactSettings.channels)
- .filter(
- (channelName) =>
- channelName !== 'phone' &&
- channelName !== 'email' &&
- channelName !== 'address',
- )
- .map((channelName, channelNameIndex) => {
- const propertyName = `contact_${channelName}`;
- return (
-
- {this.state.contact[propertyName]
- ? this.state.contact[
+ : null}
+
+ );
+ })}
+ {Object.keys(this.props.contactSettings.channels)
+ .filter(
+ (channelName) =>
+ channelName !== 'phone' &&
+ channelName !== 'email' &&
+ channelName !== 'address',
+ )
+ .map((channelName, channelNameIndex) => {
+ const propertyName = `contact_${channelName}`;
+ return (
+
+ {this.state.contact[propertyName]
+ ? this.state.contact[
propertyName
].map((socialMedia, socialMediaIndex) =>
socialMedia.key && !socialMedia.delete
? this.renderSocialMediaField(
- socialMediaIndex,
- socialMedia,
- propertyName,
- channelName,
- )
+ socialMediaIndex,
+ socialMedia,
+ propertyName,
+ channelName,
+ )
: null,
)
- : null}
-
- );
- })}
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.gender.name}
-
-
-
-
-
-
-
-
-
-
-
- {Object.keys(this.props.contactSettings.fields.gender.values).map(
- (key) => {
- const optionData = this.props.contactSettings.fields.gender.values[
- key
- ];
- return ;
- },
- )}
-
-
-
-
-
+ : null}
+
+ );
+ })}
+
+
+
+
+
+
+
+
{i18n.t('contactDetailScreen.initialComment')}
-
-
-
-
-
+
+
+
+
+
+
-
- {i18n.t('global.moreFields')}
-
-
- {this.state.moreFields ? (
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.age.name}
-
-
-
-
-
-
-
-
-
-
-
- {Object.keys(this.props.contactSettings.fields.age.values).map(
- (key) => {
- const optionData = this.props.contactSettings.fields.age.values[
- key
- ];
- return (
-
- );
- },
- )}
-
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.channels.address.label}
-
-
-
+ {i18n.t('global.moreFields')}
+
+
+ {this.state.moreFields ? (
+
+
+
+
-
-
- {this.state.contact.contact_address ? (
- this.state.contact.contact_address.map((address, index) =>
- !address.delete ? (
-
-
-
-
-
-
-
- {
- this.onAddressFieldChange(value, index, address.key, this);
- }}
- style={styles.contactTextField}
- />
-
-
- {
- this.onRemoveAddressField(index, this);
- }}
- />
-
-
- ) : null,
- )
- ) : (
-
- )}
-
-
- {this.props.contactSettings.fields.location_grid.name}
+
+
+
+
+ {this.props.contactSettings.fields.gender.name}
-
-
-
- {
- geonamesSelectizeRef = selectize;
- }}
- itemId="value"
- items={this.state.foundGeonames}
- selectedItems={[]}
- textInputProps={{
- placeholder: i18n.t('contactDetailScreen.selectLocations'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+ {Object.keys(this.props.contactSettings.fields.gender.values).map(
+ (key) => {
+ const optionData = this.props.contactSettings.fields.gender
+ .values[key];
+ return (
+
+ );
+ },
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.age.name}
+
+
+
+
+
+
+
+
+
+
+
+ {Object.keys(this.props.contactSettings.fields.age.values).map(
+ (key) => {
+ const optionData = this.props.contactSettings.fields.age.values[
+ key
+ ];
+ return (
+
+ );
+ },
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.people_groups.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ peopleGroupsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={this.state.peopleGroups}
+ selectedItems={this.getSelectizeItems(
+ this.state.contact.people_groups,
+ this.state.peopleGroups,
+ )}
+ textInputProps={{
+ placeholder: i18n.t('global.selectPeopleGroups'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
-
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- textInputProps={{
- onChangeText: this.searchLocationsDelayed,
- }}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.contactSettings.fields.people_groups.name}
-
-
-
-
-
-
-
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+
-
-
-
- {
- peopleGroupsSelectizeRef = selectize;
- }}
- itemId="value"
- items={this.state.peopleGroups}
- selectedItems={this.getSelectizeItems(
- this.state.contact.people_groups,
- this.state.peopleGroups,
- )}
- textInputProps={{
- placeholder: i18n.t('global.selectPeopleGroups'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.channels.address.label}
+
+
+
+
+
+
+ {this.state.contact.contact_address ? (
+ this.state.contact.contact_address.map((address, index) =>
+ !address.delete ? (
+
+
+
+
+
+
+
+ {
+ this.onAddressFieldChange(value, index, address.key, this);
+ }}
+ style={styles.contactTextField}
+ />
+
+
+ {
+ this.onRemoveAddressField(index, this);
+ }}
+ />
+
+
+ ) : null,
+ )
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+ {this.props.contactSettings.fields.location_grid.name}
+
+
+
+
+
+ {
+ geonamesSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={this.state.foundGeonames}
+ selectedItems={[]}
+ textInputProps={{
+ placeholder: i18n.t('contactDetailScreen.selectLocations'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
-
- )}
- filterOnKey="name"
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
+ {item.name}
+
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+
+ )}
+ filterOnKey="name"
+ inputContainerStyle={styles.selectizeField}
+ textInputProps={{
+ onChangeText: this.searchLocationsDelayed,
+ }}
+ />
+
+
+
+
+
+
+
+
+
{this.props.contactSettings.fields.sources.name}
-
-
-
- {this.renderSourcePickerItems()}
-
-
-
- ) : null}
-
-
-
- )}
+
+
+
+
+ {this.renderSourcePickerItems()}
+
+
+
+ ) : null}
+
+
+
+ )}
)}
{successToast}
@@ -5925,13 +6462,7 @@ ContactDetailScreen.propTypes = {
code: PropTypes.any,
message: PropTypes.any,
}),
- newComment: PropTypes.shape({
- ID: PropTypes.string,
- author: PropTypes.string,
- content: PropTypes.string,
- date: PropTypes.string,
- gravatar: PropTypes.string,
- }),
+ newComment: PropTypes.bool,
contactsReducerError: PropTypes.shape({
code: PropTypes.any,
message: PropTypes.any,
@@ -6062,6 +6593,8 @@ ContactDetailScreen.defaultProps = {
isConnected: null,
contactSettings: null,
isRTL: false,
+ questionnaires: [],
+ previousContacts: [],
};
const mapStateToProps = (state) => ({
@@ -6084,6 +6617,9 @@ const mapStateToProps = (state) => ({
groupsList: state.groupsReducer.groups,
contactsList: state.contactsReducer.contacts,
isRTL: state.i18nReducer.isRTL,
+ questionnaires: state.questionnaireReducer.questionnaires,
+ previousContacts: state.contactsReducer.previousContacts,
+ previousGroups: state.groupsReducer.previousGroups,
});
const mapDispatchToProps = (dispatch) => ({
@@ -6096,14 +6632,14 @@ const mapDispatchToProps = (dispatch) => ({
getByIdEnd: () => {
dispatch(getByIdEnd());
},
- getComments: (domain, token, contactId, offset, limit) => {
- dispatch(getCommentsByContact(domain, token, contactId, offset, limit));
+ getComments: (domain, token, contactId, pagination) => {
+ dispatch(getCommentsByContact(domain, token, contactId, pagination));
},
saveComment: (domain, token, contactId, commentData) => {
dispatch(saveComment(domain, token, contactId, commentData));
},
- getActivities: (domain, token, contactId, offset, limit) => {
- dispatch(getActivitiesByContact(domain, token, contactId, offset, limit));
+ getActivities: (domain, token, contactId, pagination) => {
+ dispatch(getActivitiesByContact(domain, token, contactId, pagination));
},
endSaveContact: () => {
dispatch(saveEnd());
@@ -6111,6 +6647,18 @@ const mapDispatchToProps = (dispatch) => ({
searchLocations: (domain, token, queryText) => {
dispatch(searchLocations(domain, token, queryText));
},
+ deleteComment: (domain, token, contactId, commentId) => {
+ dispatch(deleteComment(domain, token, contactId, commentId));
+ },
+ loadingFalse: () => {
+ dispatch(loadingFalse());
+ },
+ updatePrevious: (previousContacts) => {
+ dispatch(updatePrevious(previousContacts));
+ },
+ updatePreviousGroups: (previousGroups) => {
+ dispatch(updatePreviousGroups(previousGroups));
+ },
});
export default connect(mapStateToProps, mapDispatchToProps)(ContactDetailScreen);
diff --git a/screens/Contact/ContactsScreen.js b/screens/Contact/ContactsScreen.js
index 0b4bb7a3..6de6f468 100644
--- a/screens/Contact/ContactsScreen.js
+++ b/screens/Contact/ContactsScreen.js
@@ -22,16 +22,18 @@ import { CheckBox } from 'react-native-elements';
import PropTypes from 'prop-types';
import Colors from '../../constants/Colors';
-import { getAll } from '../../store/actions/contacts.actions';
+import { getAll, updatePrevious } from '../../store/actions/contacts.actions';
import dtIcon from '../../assets/images/dt-icon.png';
import i18n from '../../languages';
import sharedTools from '../../shared';
const styles = StyleSheet.create({
flatListItem: {
- height: 40,
+ height: 40 /* this needs auto sizing */,
backgroundColor: 'white',
margin: 20,
+ marginTop: 10,
+ paddingBottom: 10,
},
contactSubtitle: {
flex: 1,
@@ -207,16 +209,24 @@ class ContactsScreen extends React.Component {
- {contact.title}
+
+ {contact.title}
+
-
+
{this.props.contactSettings.fields.overall_status.values[contact.overall_status]
? this.props.contactSettings.fields.overall_status.values[contact.overall_status]
- .label
+ .label
: ''}
{this.props.contactSettings.fields.overall_status.values[contact.overall_status] &&
- this.props.contactSettings.fields.seeker_path.values[contact.seeker_path]
+ this.props.contactSettings.fields.seeker_path.values[contact.seeker_path]
? ' • '
: ''}
{this.props.contactSettings.fields.seeker_path.values[contact.seeker_path]
@@ -225,7 +235,17 @@ class ContactsScreen extends React.Component {
-
+
);
- onRefresh = (pagination = false) => {
- if (pagination) {
- this.setState(
- (prevState) => ({
- offset: prevState.offset + prevState.limit,
- filtered: false,
- search: '',
- searchBarFilter: {
- ...prevState.searchBarFilter,
- toggle: false,
- currentFilter: '',
- },
- }),
- () => {
- this.props.getAllContacts(
- this.props.userData.domain,
- this.props.userData.token,
- this.state.offset,
- this.state.limit,
- this.state.sort,
- );
- },
- );
- } else {
- this.setState(
- (prevState) => ({
- offset: 0,
- filtered: false,
- search: '',
- searchBarFilter: {
- ...prevState.searchBarFilter,
- toggle: false,
- currentFilter: '',
- },
- }),
- () => {
- this.props.getAllContacts(
- this.props.userData.domain,
- this.props.userData.token,
- this.state.offset,
- this.state.limit,
- this.state.sort,
- );
- },
- );
- }
+ onRefresh = (increasePagination = false, returnFromDetail = false) => {
+ let newState = {
+ offset: increasePagination ? this.state.offset + this.state.limit : 0,
+ filtered: false,
+ search: '',
+ searchBarFilter: {
+ ...this.state.searchBarFilter,
+ toggle: false,
+ currentFilter: '',
+ },
+ };
+ this.setState(
+ (prevState) => {
+ return returnFromDetail ? prevState : newState;
+ },
+ () => {
+ this.props.getAllContacts(
+ this.props.userData.domain,
+ this.props.userData.token,
+ this.state.offset,
+ this.state.limit,
+ this.state.sort,
+ );
+ },
+ );
};
goToContactDetailScreen = (contactData = null) => {
if (contactData) {
+ this.props.updatePrevious([
+ {
+ contactId: parseInt(contactData.ID),
+ onlyView: true,
+ contactName: contactData.title,
+ },
+ ]);
// Detail
this.props.navigation.navigate('ContactDetail', {
contactId: contactData.ID,
onlyView: true,
contactName: contactData.title,
- previousList: [],
- onGoBack: () => this.onRefresh(),
+ onGoBack: () => this.onRefresh(false, true),
});
} else {
+ this.props.updatePrevious([]);
// Create
this.props.navigation.navigate('ContactDetail', {
- previousList: [],
onlyView: true,
- onGoBack: () => this.onRefresh(),
+ onGoBack: () => this.onRefresh(false, true),
});
}
};
@@ -428,14 +434,14 @@ class ContactsScreen extends React.Component {
}
if (queryFilterTwo[key] === 'me') {
if (key == 'assigned_to') {
- queryFilterTwo[key] = `user-${this.props.userData.id}`;
+ queryFilterTwo[key] = this.props.userData.id;
} else {
queryFilterTwo[key] = this.props.userData.id.toString();
}
}
});
// Remove subassigned query because contacts does not have this value
- if(Object.prototype.hasOwnProperty.call(queryFilterTwo, "subassigned")) {
+ if (Object.prototype.hasOwnProperty.call(queryFilterTwo, 'subassigned')) {
delete queryFilterTwo.subassigned;
}
// Filter contacts according to 'queryFilterTwo' filters
@@ -447,12 +453,16 @@ class ContactsScreen extends React.Component {
if (Object.prototype.hasOwnProperty.call(contact, key)) {
// Value is to 'omit' contacts (-closed)
if (queryFilterTwo[key].toString().startsWith('-')) {
- if (contact[key] !== queryFilterTwo[key].replace("-", "")) {
+ if (contact[key] !== queryFilterTwo[key].replace('-', '')) {
result = true;
}
// Same value as filter
} else if (queryFilterTwo[key] === contact[key]) {
result = true;
+ } else if (key == 'assigned_to') {
+ if (queryFilterTwo[key] === contact[key].key) {
+ result = true;
+ }
}
}
resp.push(result);
@@ -771,6 +781,9 @@ const mapDispatchToProps = (dispatch) => ({
getAllContacts: (domain, token, offset, limit, sort) => {
dispatch(getAll(domain, token, offset, limit, sort));
},
+ updatePrevious: (previousContacts) => {
+ dispatch(updatePrevious(previousContacts));
+ },
});
export default connect(mapStateToProps, mapDispatchToProps)(ContactsScreen);
diff --git a/screens/Group/GroupDetailScreen.js b/screens/Group/GroupDetailScreen.js
index 7b3baae6..5b1a0fa0 100644
--- a/screens/Group/GroupDetailScreen.js
+++ b/screens/Group/GroupDetailScreen.js
@@ -14,21 +14,24 @@ import {
TouchableHighlight,
BackHandler,
ActivityIndicator,
+ KeyboardAvoidingView,
} from 'react-native';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import ExpoFileSystemStorage from 'redux-persist-expo-filesystem';
-import { Label, Input, Icon, Picker, DatePicker } from 'native-base';
+import { Label, Input, Icon, Picker, DatePicker, Button } from 'native-base';
import Toast from 'react-native-easy-toast';
import { Col, Row, Grid } from 'react-native-easy-grid';
import { Chip, Selectize } from 'react-native-material-selectize';
+import ActionButton from 'react-native-action-button';
import { TabView, TabBar } from 'react-native-tab-view';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import { NavigationActions, StackActions } from 'react-navigation';
import MentionsTextInput from 'react-native-mentions';
import ParsedText from 'react-native-parsed-text';
-import * as Sentry from 'sentry-expo';
+//import * as Sentry from 'sentry-expo';
+import { BlurView } from 'expo-blur';
import moment from '../../languages/moment';
import sharedTools from '../../shared';
@@ -40,8 +43,13 @@ import {
getActivitiesByGroup,
getByIdEnd,
searchLocations,
+ deleteComment,
+ loadingFalse,
+ updatePrevious,
} from '../../store/actions/groups.actions';
+import { updatePrevious as updatePreviousContacts } from '../../store/actions/contacts.actions';
import Colors from '../../constants/Colors';
+import statusIcon from '../../assets/icons/status.png';
import baptismIcon from '../../assets/icons/baptism.png';
import bibleStudyIcon from '../../assets/icons/word.png';
import communionIcon from '../../assets/icons/communion.png';
@@ -69,11 +77,12 @@ import i18n from '../../languages';
let toastSuccess;
let toastError;
-const containerPadding = 35;
+const containerPadding = 20;
const windowWidth = Dimensions.get('window').width;
const spacing = windowWidth * 0.025;
const sideSize = windowWidth - 2 * spacing;
const circleSideSize = windowWidth / 3 + 20;
+const windowHeight = Dimensions.get('window').height;
let keyboardDidShowListener, keyboardDidHideListener, focusListener, hardwareBackPressListener;
//const hasNotch = Platform.OS === 'android' && StatusBar.currentHeight > 25;
//const extraNotchHeight = hasNotch ? StatusBar.currentHeight : 0;
@@ -149,10 +158,17 @@ const styles = StyleSheet.create({
},
tabStyle: { backgroundColor: '#FFFFFF' },
textStyle: { color: 'gray' },
+ fieldsIcons: {
+ height: 22,
+ width: 22,
+ },
addRemoveIcons: {
fontSize: 30,
marginRight: 0,
+ color: Colors.addRemoveIcons,
},
+ addIcons: { color: 'green' },
+ removeIcons: { color: 'red' },
// Comments Section
container: {
paddingLeft: 19,
@@ -187,6 +203,10 @@ const styles = StyleSheet.create({
color: Colors.tintColor,
fontSize: 10,
},
+ groupFABIcon: {
+ color: 'white',
+ fontSize: 20,
+ },
separator: {
height: 1,
backgroundColor: '#CCCCCC',
@@ -204,13 +224,13 @@ const styles = StyleSheet.create({
// Form
formContainer: {
paddingTop: 10,
- paddingBottom: 10,
+ paddingBottom: 100,
paddingLeft: containerPadding,
paddingRight: containerPadding,
},
formRow: {
- paddingTop: 20,
- paddingBottom: 20,
+ paddingTop: 15,
+ paddingBottom: 15,
width: '100%',
},
formIconLabel: { marginLeft: 10, width: 'auto' },
@@ -240,8 +260,6 @@ const styles = StyleSheet.create({
formDivider: {
borderBottomColor: '#CCCCCC',
borderBottomWidth: 1,
- marginLeft: 10,
- marginRight: 10,
},
formDivider2: {
marginTop: 25,
@@ -255,6 +273,7 @@ const styles = StyleSheet.create({
},
formIconLabelCol: {
width: 35,
+ marginRight: 10,
},
formIconLabelView: {
alignItems: 'center',
@@ -346,9 +365,8 @@ const styles = StyleSheet.create({
},
noCommentsContainer: {
padding: 20,
- textAlignVertical: 'top',
- textAlign: 'center',
- height: 300,
+ height: '90%',
+ transform: [{ scaleY: -1 }],
},
noCommentsImage: {
opacity: 0.5,
@@ -357,19 +375,10 @@ const styles = StyleSheet.create({
padding: 10,
},
noCommentsText: {
- textAlignVertical: 'center',
- textAlign: 'center',
- fontWeight: 'bold',
- color: '#A8A8A8',
- padding: 5,
- },
- noCommentsTextOffilne: {
- textAlignVertical: 'center',
textAlign: 'center',
fontWeight: 'bold',
color: '#A8A8A8',
- backgroundColor: '#fff2ac',
- padding: 5,
+ marginTop: 10,
},
membersCount: {
color: Colors.tintColor,
@@ -459,6 +468,37 @@ const styles = StyleSheet.create({
fontSize: 12,
color: 'rgba(0,0,0,0.6)',
},
+ // Edit/Delete comment dialog
+ dialogBackground: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ },
+ dialogBox: {
+ backgroundColor: '#FFFFFF',
+ padding: 20,
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ height: windowHeight - windowHeight * 0.55,
+ width: windowWidth - windowWidth * 0.1,
+ marginTop: windowHeight * 0.1,
+ },
+ dialogButton: {
+ backgroundColor: Colors.tintColor,
+ borderRadius: 5,
+ width: 100,
+ marginTop: 20,
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ },
+ dialogContent: {
+ height: '100%',
+ width: '100%',
+ fontSize: 20,
+ textAlign: 'center',
+ color: Colors.grayDark,
+ marginBottom: 5,
+ },
});
const initialState = {
@@ -472,18 +512,26 @@ const initialState = {
geonames: [],
peopleGroups: [],
groups: [],
- comments: [],
+ comments: {
+ data: [],
+ pagination: {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ },
+ },
loadComments: false,
loadMoreComments: false,
- totalComments: 0,
- commentsOffset: 0,
- commentsLimit: 10,
- activities: [],
+ activities: {
+ data: [],
+ pagination: {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ },
+ },
loadActivities: false,
loadMoreActivities: false,
- totalActivities: 0,
- activitiesOffset: 0,
- activitiesLimit: 10,
showAssignedToModal: false,
groupStatusBackgroundColor: '#ffffff',
loading: false,
@@ -511,7 +559,12 @@ const initialState = {
membersContacts: [],
unmodifiedMembersContacts: [],
assignedToContacts: [],
- unmodifedAssignedToContacts: []
+ unmodifedAssignedToContacts: [],
+ commentDialog: {
+ toggle: false,
+ data: {},
+ delete: false,
+ },
};
const safeFind = (found, prop) => {
@@ -571,9 +624,7 @@ class GroupDetailScreen extends React.Component {
{
- params.backButtonTap();
- }}
+ onPress={params.backButtonTap}
style={[{ paddingLeft: 16, color: '#FFFFFF', paddingRight: 16 }]}
/>
);
@@ -608,13 +659,13 @@ class GroupDetailScreen extends React.Component {
fontWeight: 'bold',
width: params.onlyView
? Platform.select({
- android: 200,
- ios: 180,
- })
+ android: 200,
+ ios: 180,
+ })
: Platform.select({
- android: 180,
- ios: 140,
- }),
+ android: 180,
+ ios: 140,
+ }),
marginLeft: params.onlyView ? undefined : 25,
},
};
@@ -627,12 +678,22 @@ class GroupDetailScreen extends React.Component {
componentDidMount() {
const { navigation } = this.props;
this.onLoad();
- navigation.setParams({
- onEnableEdit: this.onEnableEdit,
- onDisableEdit: this.onDisableEdit,
- onSaveGroup: this.onSaveGroup,
- backButtonTap: this.backButtonTap,
- });
+
+ let params = {
+ onEnableEdit: this.onEnableEdit.bind(this),
+ onDisableEdit: this.onDisableEdit.bind(this),
+ onSaveGroup: this.onSaveGroup.bind(this),
+ backButtonTap: this.backButtonTap.bind(this),
+ };
+ // Add afterBack param to execute 'parents' functions (ContactsView, NotificationsView)
+ if (!navigation.state.params.afterBack) {
+ params = {
+ ...params,
+ afterBack: this.afterBack.bind(this),
+ };
+ }
+ navigation.setParams(params);
+
keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
this.keyboardDidShow.bind(this),
@@ -642,34 +703,21 @@ class GroupDetailScreen extends React.Component {
this.keyboardDidHide.bind(this),
);
focusListener = navigation.addListener('didFocus', () => {
- if (
- typeof this.props.navigation.state.params.groupId !== 'undefined' &&
- this.state.loadedLocal
- ) {
- this.setState(
- {
- loading: false,
- },
- () => {
- this.onRefresh(this.props.navigation.state.params.groupId);
- },
- );
+ //Focus on 'detail mode' (going back or open detail view)
+ if (typeof this.props.navigation.state.params.groupId !== 'undefined') {
+ this.props.loadingFalse();
+ this.onRefresh(this.props.navigation.state.params.groupId, true);
}
});
+ // Android bottom back button listener
hardwareBackPressListener = BackHandler.addEventListener('hardwareBackPress', () => {
- sharedTools.onlyExecuteLastCall(
- null,
- () => {
- this.backButtonTap();
- },
- 1000,
- );
+ this.props.navigation.state.params.backButtonTap();
return true;
});
}
componentDidCatch(error, errorInfo) {
- Sentry.captureException(errorInfo);
+ //Sentry.captureException(errorInfo);
}
componentWillUnmount() {
@@ -684,37 +732,23 @@ class GroupDetailScreen extends React.Component {
group,
loading,
comments,
- totalComments,
loadingComments,
activities,
- totalActivities,
loadingActivities,
- newComment,
foundGeonames,
isConnected,
} = nextProps;
let newState = {
...prevState,
loading,
- comments: comments || prevState.comments,
- totalComments: totalComments || prevState.totalComments,
+ comments: prevState.comments,
loadComments: loadingComments,
- activities: activities || prevState.activities,
- totalActivities: totalActivities || prevState.totalActivities,
+ activities: prevState.activities,
loadActivities: loadingActivities,
group: prevState.group,
unmodifiedGroup: prevState.unmodifiedGroup,
};
- // NEW COMMENT
- if (newComment) {
- newState.comments.unshift(newComment);
- newState = {
- ...newState,
- comments: newState.comments,
- };
- }
-
// SAVE / GET BY ID
if (group) {
newState = {
@@ -726,9 +760,6 @@ class GroupDetailScreen extends React.Component {
...group,
},
};
- if (newState.group.oldID) {
- delete newState.group.oldID;
- }
if (newState.group.group_status) {
newState = {
...newState,
@@ -792,15 +823,16 @@ class GroupDetailScreen extends React.Component {
};
}
if (newState.group.coaches) {
-
// Clear collection
newState = {
...newState,
- groupCoachContacts: []
+ groupCoachContacts: [],
};
newState.group.coaches.values.forEach((coachContact) => {
- const foundCoachContact = newState.usersContacts.find((user) => user.value === coachContact.value);
+ const foundCoachContact = newState.usersContacts.find(
+ (user) => user.value === coachContact.value,
+ );
if (!foundCoachContact) {
// Add non existent coach contact in usersContacts list (user does not have access permission to this contacts)
newState = {
@@ -809,31 +841,31 @@ class GroupDetailScreen extends React.Component {
...newState.groupCoachContacts,
{
name: coachContact.name,
- value: coachContact.value
- }
+ value: coachContact.value,
+ },
],
unmodifiedGroupCoachContacts: [
...newState.unmodifiedGroupCoachContacts,
{
name: coachContact.name,
- value: coachContact.value
- }
- ]
+ value: coachContact.value,
+ },
+ ],
};
}
});
-
}
if (newState.group.parent_groups) {
-
// Clear collection
newState = {
...newState,
- parentGroups: []
+ parentGroups: [],
};
newState.group.parent_groups.values.forEach((parentGroup) => {
- const foundParentGroup = newState.groups.find((groups) => groups.value === parentGroup.value);
+ const foundParentGroup = newState.groups.find(
+ (groups) => groups.value === parentGroup.value,
+ );
if (!foundParentGroup) {
// Add non existent parent group in groups list (user does not have access permission to this group/s)
newState = {
@@ -842,27 +874,25 @@ class GroupDetailScreen extends React.Component {
...newState.parentGroups,
{
name: parentGroup.name,
- value: parentGroup.value
- }
+ value: parentGroup.value,
+ },
],
unmodifiedParentGroups: [
...newState.unmodifiedParentGroups,
{
name: parentGroup.name,
- value: parentGroup.value
- }
- ]
+ value: parentGroup.value,
+ },
+ ],
};
}
});
-
}
if (newState.group.peer_groups) {
-
// Clear collection
newState = {
...newState,
- peerGroups: []
+ peerGroups: [],
};
newState.group.peer_groups.values.forEach((peerGroup) => {
@@ -875,31 +905,31 @@ class GroupDetailScreen extends React.Component {
...newState.peerGroups,
{
name: peerGroup.name,
- value: peerGroup.value
- }
+ value: peerGroup.value,
+ },
],
unmodifiedPeerGroups: [
...newState.unmodifiedPeerGroups,
{
name: peerGroup.name,
- value: peerGroup.value
- }
- ]
+ value: peerGroup.value,
+ },
+ ],
};
}
});
-
}
if (newState.group.child_groups) {
-
// Clear collection
newState = {
...newState,
- childGroups: []
+ childGroups: [],
};
newState.group.child_groups.values.forEach((childGroup) => {
- const foundChildGroup = newState.groups.find((groups) => groups.value === childGroup.value);
+ const foundChildGroup = newState.groups.find(
+ (groups) => groups.value === childGroup.value,
+ );
if (!foundChildGroup) {
// Add non existent child group in groups list (user does not have access permission to this group/s)
newState = {
@@ -908,31 +938,31 @@ class GroupDetailScreen extends React.Component {
...newState.childGroups,
{
name: childGroup.name,
- value: childGroup.value
- }
+ value: childGroup.value,
+ },
],
unmodifiedChildGroups: [
...newState.unmodifiedChildGroups,
{
name: childGroup.name,
- value: childGroup.value
- }
- ]
+ value: childGroup.value,
+ },
+ ],
};
}
});
-
}
if (newState.group.members) {
-
// Clear collection
newState = {
...newState,
- membersContacts: []
+ membersContacts: [],
};
newState.group.members.values.forEach((member) => {
- const foundMember = newState.usersContacts.find((contact) => contact.value === member.value);
+ const foundMember = newState.usersContacts.find(
+ (contact) => contact.value === member.value,
+ );
if (!foundMember) {
// Add non existent member contact in members list (user does not have access permission to this contact/s)
newState = {
@@ -941,30 +971,30 @@ class GroupDetailScreen extends React.Component {
...newState.membersContacts,
{
name: member.name,
- value: member.value
- }
+ value: member.value,
+ },
],
unmodifiedMembersContacts: [
...newState.unmodifiedMembersContacts,
{
name: member.name,
- value: member.value
- }
- ]
+ value: member.value,
+ },
+ ],
};
}
});
-
}
if (newState.group.assigned_to) {
-
// Clear collection
newState = {
...newState,
- assignedToContacts: []
+ assignedToContacts: [],
};
- let foundAssigned = newState.users.find((user) => user.key === newState.group.assigned_to.key);
+ let foundAssigned = newState.users.find(
+ (user) => user.key === newState.group.assigned_to.key,
+ );
if (!foundAssigned) {
// Add non existent group to list (user does not have access permission to this groups)
newState = {
@@ -972,55 +1002,65 @@ class GroupDetailScreen extends React.Component {
assignedToContacts: [
...newState.assignedToContacts,
{
- label: foundAssigned.label,
- key: foundAssigned.key
- }
+ label: newState.group.assigned_to.label,
+ key: newState.group.assigned_to.key,
+ },
],
unmodifedAssignedToContacts: [
...newState.unmodifedAssignedToContacts,
{
- label: foundAssigned.label,
- key: foundAssigned.key
- }
- ]
+ label: newState.group.assigned_to.label,
+ key: newState.group.assigned_to.key,
+ },
+ ],
};
}
-
}
}
// GET COMMENTS
if (comments) {
- // NEW COMMENTS (PAGINATION)
- if (prevState.commentsOffset > 0) {
+ if (newState.group.ID && Object.prototype.hasOwnProperty.call(comments, newState.group.ID)) {
+ // NEW COMMENTS (PAGINATION)
+ if (comments[newState.group.ID].pagination.offset > 0) {
+ newState = {
+ ...newState,
+ loadingMoreComments: false,
+ };
+ }
+ // ONLINE MODE: USE STATE PAGINATION - OFFLINE MODE: USE STORE PAGINATION
+ // UPDATE OFFSET
newState = {
...newState,
- comments: prevState.comments.concat(comments),
- loadMoreComments: false,
+ comments: {
+ ...comments[newState.group.ID],
+ },
};
}
- newState = {
- // UPDATE OFFSET
- ...newState,
- commentsOffset: prevState.commentsOffset + prevState.commentsLimit,
- };
}
// GET ACTIVITITES
if (activities) {
- // NEW ACTIVITIES (PAGINATION)
- if (prevState.activitiesOffset > 0) {
+ if (
+ newState.group.ID &&
+ Object.prototype.hasOwnProperty.call(activities, newState.group.ID)
+ ) {
+ // NEW ACTIVITIES (PAGINATION)
+ if (activities[newState.group.ID].pagination.offset > 0) {
+ newState = {
+ ...newState,
+ loadingMoreActivities: false,
+ };
+ }
+ // ONLINE MODE: USE STATE PAGINATION - OFFLINE MODE: USE STORE PAGINATION
+ // UPDATE OFFSET
newState = {
...newState,
- activities: prevState.activities.concat(activities),
- loadMoreActivities: false,
+ activities: {
+ ...activities[newState.group.ID],
+ },
};
}
- newState = {
- // UPDATE OFFSET
- ...newState,
- activitiesOffset: prevState.activitiesOffset + prevState.activitiesLimit,
- };
}
// GET FILTERED LOCATIONS
@@ -1055,15 +1095,30 @@ class GroupDetailScreen extends React.Component {
// Update group data only in these conditions:
// Same group created (offline/online)
// Same group updated (offline/online)
- // Sane offline group created in DB (AutoID to DBID)
+ // Same offline group created in DB (AutoID to DBID)
if (
(typeof group.ID !== 'undefined' && typeof this.state.group.ID === 'undefined') ||
- group.ID.toString() === this.state.group.ID.toString() ||
- (group.oldID && group.oldID.toString() === this.state.group.ID.toString())
+ (group.ID && group.ID.toString() === this.state.group.ID.toString()) ||
+ (group.oldID && group.oldID === this.state.group.ID.toString())
) {
// Highlight Updates -> Compare this.state.group with group and show differences
navigation.setParams({ groupName: group.title, groupId: group.ID });
this.getGroupByIdEnd();
+ // Add group to 'previousGroups' array on creation
+ if (
+ !this.props.previousGroups.find(
+ (previousGroup) => parseInt(previousGroup.groupId) === parseInt(group.ID),
+ )
+ ) {
+ this.props.updatePrevious([
+ ...this.props.previousGroups,
+ {
+ groupId: parseInt(group.ID),
+ onlyView: true,
+ groupName: group.title,
+ },
+ ]);
+ }
}
}
@@ -1075,11 +1130,11 @@ class GroupDetailScreen extends React.Component {
// Sane offline group created in DB (AutoID to DBID)
if (
(typeof group.ID !== 'undefined' && typeof this.state.group.ID === 'undefined') ||
- group.ID.toString() === this.state.group.ID.toString() ||
- (group.oldID && group.oldID.toString() === this.state.group.ID.toString())
+ (group.ID && group.ID.toString() === this.state.group.ID.toString()) ||
+ (group.oldID && group.oldID === this.state.group.ID.toString())
) {
// Highlight Updates -> Compare this.state.contact with contact and show differences
- this.onRefreshCommentsActivities(group.ID);
+ this.onRefreshCommentsActivities(group.ID, true);
toastSuccess.show(
{i18n.t('global.success.save')}
@@ -1110,11 +1165,12 @@ class GroupDetailScreen extends React.Component {
3000,
);
}
-
+ // Fix to press back button in comments tab
if (prevProps.navigation.state.params.hideTabBar !== navigation.state.params.hideTabBar) {
if (!navigation.state.params.hideTabBar && this.state.executingBack) {
setTimeout(() => {
- this.executeBack(navigation, navigation.state.params);
+ navigation.goBack(null);
+ navigation.state.params.afterBack();
}, 1000);
}
}
@@ -1147,15 +1203,35 @@ class GroupDetailScreen extends React.Component {
},
);
} else {
- this.executeBack(navigation, params);
+ //Fix to returning using Android back button! -> goBack(null)
+ navigation.goBack(null);
+ navigation.state.params.afterBack();
}
};
- executeBack = (navigation, params) => {
- if (params.previousList.length > 0) {
- navigation.goBack();
- params.onBackFromSameScreen();
- } else if (params.fromNotificationView) {
+ afterBack = () => {
+ let { navigation } = this.props;
+ let newPreviousGroups = [...this.props.previousGroups];
+ newPreviousGroups.pop();
+ this.props.updatePrevious(newPreviousGroups);
+ if (newPreviousGroups.length > 0) {
+ this.props.loadingFalse();
+ let currentParams = {
+ ...newPreviousGroups[newPreviousGroups.length - 1],
+ };
+ this.setState({
+ group: {
+ ID: currentParams.groupId,
+ title: currentParams.groupName,
+ group_type: 'group',
+ },
+ groupStatusBackgroundColor: '#ffffff',
+ });
+ navigation.setParams({
+ ...currentParams,
+ });
+ this.onRefresh(currentParams.groupId, true);
+ } else if (navigation.state.params.fromNotificationView) {
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'GroupList' })],
@@ -1165,8 +1241,8 @@ class GroupDetailScreen extends React.Component {
} else {
navigation.goBack();
// Prevent error when view loaded from ContactDetailScreen.js
- if (typeof params.onGoBack === 'function') {
- params.onGoBack();
+ if (typeof navigation.state.params.onGoBack === 'function') {
+ navigation.state.params.onGoBack();
}
}
};
@@ -1225,26 +1301,16 @@ class GroupDetailScreen extends React.Component {
});
};
- onRefresh(groupId) {
- this.getGroupById(groupId);
- this.onRefreshCommentsActivities(groupId);
+ onRefresh(groupId, forceRefresh = false) {
+ if (!self.state.loading || forceRefresh) {
+ this.getGroupById(groupId);
+ this.onRefreshCommentsActivities(groupId, true);
+ }
}
- onRefreshCommentsActivities(groupId) {
- this.setState(
- {
- comments: [],
- activities: [],
- commentsOffset: 0,
- activitiesOffset: 0,
- },
- () => {
- this.getGroupComments(groupId);
- if (this.props.isConnected) {
- this.getGroupActivities(groupId);
- }
- },
- );
+ onRefreshCommentsActivities(groupId, resetPagination = false) {
+ this.getGroupComments(groupId, resetPagination);
+ this.getGroupActivities(groupId, resetPagination);
}
getLists = async (groupId) => {
@@ -1306,27 +1372,51 @@ class GroupDetailScreen extends React.Component {
this.props.getByIdEnd();
}
- getGroupComments(groupId) {
- if (!this.state.loadComments) {
- this.props.getComments(
- this.props.userData.domain,
- this.props.userData.token,
- groupId,
- this.state.commentsOffset,
- this.state.commentsLimit,
- );
+ getGroupComments(groupId, resetPagination = false) {
+ if (this.props.isConnected) {
+ if (resetPagination) {
+ this.props.getComments(this.props.userData.domain, this.props.userData.token, groupId, {
+ offset: 0,
+ limit: 10,
+ });
+ } else {
+ //ONLY GET DATA IF THERE IS MORE DATA TO GET
+ if (
+ !this.state.loadComments &&
+ this.state.comments.pagination.offset < this.state.comments.pagination.total
+ ) {
+ this.props.getComments(
+ this.props.userData.domain,
+ this.props.userData.token,
+ groupId,
+ this.state.comments.pagination,
+ );
+ }
+ }
}
}
- getGroupActivities(groupId) {
- if (!this.state.loadActivities) {
- this.props.getActivities(
- this.props.userData.domain,
- this.props.userData.token,
- groupId,
- this.state.activitiesOffset,
- this.state.activitiesLimit,
- );
+ getGroupActivities(groupId, resetPagination = false) {
+ if (this.props.isConnected) {
+ if (resetPagination) {
+ this.props.getActivities(this.props.userData.domain, this.props.userData.token, groupId, {
+ offset: 0,
+ limit: 10,
+ });
+ } else {
+ //ONLY GET DATA IF THERE IS MORE DATA TO GET
+ if (
+ !this.state.loadActivities &&
+ this.state.activities.pagination.offset < this.state.activities.pagination.total
+ ) {
+ this.props.getActivities(
+ this.props.userData.domain,
+ this.props.userData.token,
+ groupId,
+ this.state.activities.pagination,
+ );
+ }
+ }
}
}
@@ -1362,11 +1452,14 @@ class GroupDetailScreen extends React.Component {
unmodifiedPeerGroups,
unmodifiedChildGroups,
unmodifiedMembersContacts,
- unmodifedAssignedToContacts
+ unmodifedAssignedToContacts,
} = this.state;
this.setState((state) => {
+ // Set correct index in Tab position according to view mode and current tab position
const indexFix =
- state.tabViewConfig.index > 1 ? state.tabViewConfig.index + 1 : state.tabViewConfig.index;
+ state.tabViewConfig.index > 1 && !state.onlyView
+ ? state.tabViewConfig.index + 1
+ : state.tabViewConfig.index;
return {
onlyView: true,
group: {
@@ -1383,7 +1476,7 @@ class GroupDetailScreen extends React.Component {
peerGroups: [...unmodifiedPeerGroups],
childGroups: [...unmodifiedChildGroups],
membersContacts: [...unmodifiedMembersContacts],
- assignedToContacts: [...unmodifedAssignedToContacts]
+ assignedToContacts: [...unmodifedAssignedToContacts],
};
});
this.props.navigation.setParams({ hideTabBar: false, onlyView: true });
@@ -1452,7 +1545,7 @@ class GroupDetailScreen extends React.Component {
getCommentsAndActivities() {
const { comments, activities } = this.state;
- const list = comments.concat(activities);
+ const list = comments.data.concat(activities.data);
return list
.filter((item, index) => list.indexOf(item) === index)
.sort((a, b) => new Date(a.date).getTime() < new Date(b.date).getTime());
@@ -1479,17 +1572,17 @@ class GroupDetailScreen extends React.Component {
{this.state.group.member_count}
) : (
-
- {' '}
+
+ {' '}
0{' '}
-
- )}
+
+ )}
{!this.state.group.member_count || parseInt(this.state.group.member_count) === 0 ? (
@@ -1498,20 +1591,23 @@ class GroupDetailScreen extends React.Component {
) : (
-
- )}
+
+ )}
);
- goToContactDetailScreen = (contactID) => {
+ goToContactDetailScreen = (contactID, name) => {
+ this.props.updatePreviousContacts([
+ {
+ contactId: contactID,
+ onlyView: true,
+ contactName: name,
+ },
+ ]);
this.props.navigation.navigate('ContactDetail', {
contactId: contactID,
onlyView: true,
- contactName: safeFind(
- this.state.usersContacts.find((user) => user.value === contactID),
- 'name',
- ),
- previousList: [],
+ contactName: name,
});
};
@@ -1536,7 +1632,8 @@ class GroupDetailScreen extends React.Component {
- {// Comment
+ {
+ // Comment
Object.prototype.hasOwnProperty.call(commentOrActivity, 'content') && (
@@ -1554,8 +1651,10 @@ class GroupDetailScreen extends React.Component {
- )}
- {// Activity
+ )
+ }
+ {
+ // Activity
Object.prototype.hasOwnProperty.call(commentOrActivity, 'object_note') && (
@@ -1573,7 +1672,8 @@ class GroupDetailScreen extends React.Component {
- )}
+ )
+ }
+ {
+ // Comment and its their own comment
+ Object.prototype.hasOwnProperty.call(commentOrActivity, 'content') &&
+ commentOrActivity.author.toLowerCase() ===
+ this.props.userData.username.toLowerCase() && (
+
+
+ {
+ this.openCommentDialog(commentOrActivity, true);
+ }}>
+
+
+ {i18n.t('global.delete')}
+
+
+ {
+ this.openCommentDialog(commentOrActivity);
+ }}>
+
+
+ {i18n.t('global.edit')}
+
+
+
+
+ )
+ }
);
@@ -1610,11 +1762,11 @@ class GroupDetailScreen extends React.Component {
key: value,
label: [...this.state.users, ...this.state.assignedToContacts].find(
(user) => user.key === value,
- ).label
+ ).label,
},
},
showAssignedToModal: false,
- assignedToContacts: [] // Clear non existing assigentToContacts list
+ assignedToContacts: [], // Clear non existing assigentToContacts list
}));
};
@@ -1765,7 +1917,7 @@ class GroupDetailScreen extends React.Component {
const foundMemberIndex = membersListCopy.indexOf(foundMember);
membersListCopy.splice(foundMemberIndex, 1);
let foundMemberContactIndex = this.state.membersContacts.findIndex(
- (memberContact) => memberContact.value === selectedValue.value
+ (memberContact) => memberContact.value === selectedValue.value,
);
let membersContacts = [...this.state.membersContacts];
if (foundMemberContactIndex > -1) {
@@ -1779,29 +1931,33 @@ class GroupDetailScreen extends React.Component {
},
},
// Remove member contact from list
- membersContacts: membersContacts
+ membersContacts: membersContacts,
}));
}
};
onSetLeader = (selectedValue) => {
- let leadersListCopy = [...this.state.group.leaders.values];
- const leaderModified = {
- ...selectedValue,
- delete:
- this.state.group.leaders &&
- leadersListCopy.find((leader) => leader.value === selectedValue.value)
- ? true
- : false,
- };
- const foundLeader = leadersListCopy.find((leader) => leader.value === selectedValue.value);
- if (foundLeader) {
- const foundLeaderIndex = leadersListCopy.indexOf(foundLeader);
- leadersListCopy[foundLeaderIndex] = {
- ...leaderModified,
- };
+ let leadersListCopy = this.state.group.leaders ? [...this.state.group.leaders.values] : [];
+ const foundLeaderIndex = leadersListCopy.findIndex(
+ (leader) => leader.value === selectedValue.value,
+ );
+ if (foundLeaderIndex > -1) {
+ // 3 Remove leader 'deletion'
+ if (leadersListCopy[foundLeaderIndex].delete) {
+ leadersListCopy[foundLeaderIndex] = {
+ ...selectedValue,
+ delete: false,
+ };
+ } else {
+ // 2 Delete leader
+ leadersListCopy[foundLeaderIndex] = {
+ ...selectedValue,
+ delete: true,
+ };
+ }
} else {
- leadersListCopy.push(leaderModified);
+ // 1 Add leader
+ leadersListCopy.push(selectedValue);
}
this.setState((prevState) => ({
group: {
@@ -1845,93 +2001,104 @@ class GroupDetailScreen extends React.Component {
return itemsToSave;
};
- transformGroupObject = (group) => {
+ transformGroupObject = (group, quickAction = {}) => {
let transformedGroup = {
...group,
};
- // if property exist, get from json, otherwise, send empty array
- if (coachesSelectizeRef) {
- transformedGroup = {
- ...transformedGroup,
- coaches: {
- values: this.getSelectizeValuesToSave(
- transformedGroup.coaches ? transformedGroup.coaches.values : [],
- coachesSelectizeRef,
- ),
- },
- };
- }
- if (geonamesSelectizeRef) {
- transformedGroup = {
- ...transformedGroup,
- location_grid: {
- values: this.getSelectizeValuesToSave(
- transformedGroup.location_grid ? transformedGroup.location_grid.values : [],
- geonamesSelectizeRef,
- ),
- },
- };
- }
- if (peopleGroupsSelectizeRef) {
+ if (
+ Object.prototype.hasOwnProperty.call(quickAction, 'quick_button_meeting_scheduled') ||
+ Object.prototype.hasOwnProperty.call(quickAction, 'quick_button_meeting_postponed') ||
+ Object.prototype.hasOwnProperty.call(quickAction, 'quick_button_meeting_complete')
+ ) {
transformedGroup = {
...transformedGroup,
- people_groups: {
- values: this.getSelectizeValuesToSave(
- transformedGroup.people_groups ? transformedGroup.people_groups.values : [],
- peopleGroupsSelectizeRef,
- ),
- },
- };
- }
- if (parentGroupsSelectizeRef) {
- transformedGroup = {
- ...transformedGroup,
- parent_groups: {
- values: this.getSelectizeValuesToSave(
- transformedGroup.parent_groups ? transformedGroup.parent_groups.values : [],
- parentGroupsSelectizeRef,
- ),
- },
- };
- }
- if (peerGroupsSelectizeRef) {
- transformedGroup = {
- ...transformedGroup,
- peer_groups: {
- values: this.getSelectizeValuesToSave(
- transformedGroup.peer_groups ? transformedGroup.peer_groups.values : [],
- peerGroupsSelectizeRef,
- ),
- },
- };
- }
- if (childGroupsSelectizeRef) {
- transformedGroup = {
- ...transformedGroup,
- child_groups: {
- values: this.getSelectizeValuesToSave(
- transformedGroup.child_groups ? transformedGroup.child_groups.values : [],
- childGroupsSelectizeRef,
- ),
- },
- };
- }
- if (addMembersSelectizeRef) {
- transformedGroup = {
- ...transformedGroup,
- members: {
- values: this.getSelectizeValuesToSave(
- this.state.unmodifiedGroup.members ? this.state.unmodifiedGroup.members.values : [],
- null,
- transformedGroup.members ? transformedGroup.members.values : [],
- ),
- },
+ ...quickAction,
};
+ } else {
+ // if property exist, get from json, otherwise, send empty array
+ if (coachesSelectizeRef) {
+ transformedGroup = {
+ ...transformedGroup,
+ coaches: {
+ values: this.getSelectizeValuesToSave(
+ transformedGroup.coaches ? transformedGroup.coaches.values : [],
+ coachesSelectizeRef,
+ ),
+ },
+ };
+ }
+ if (geonamesSelectizeRef) {
+ transformedGroup = {
+ ...transformedGroup,
+ location_grid: {
+ values: this.getSelectizeValuesToSave(
+ transformedGroup.location_grid ? transformedGroup.location_grid.values : [],
+ geonamesSelectizeRef,
+ ),
+ },
+ };
+ }
+ if (peopleGroupsSelectizeRef) {
+ transformedGroup = {
+ ...transformedGroup,
+ people_groups: {
+ values: this.getSelectizeValuesToSave(
+ transformedGroup.people_groups ? transformedGroup.people_groups.values : [],
+ peopleGroupsSelectizeRef,
+ ),
+ },
+ };
+ }
+ if (parentGroupsSelectizeRef) {
+ transformedGroup = {
+ ...transformedGroup,
+ parent_groups: {
+ values: this.getSelectizeValuesToSave(
+ transformedGroup.parent_groups ? transformedGroup.parent_groups.values : [],
+ parentGroupsSelectizeRef,
+ ),
+ },
+ };
+ }
+ if (peerGroupsSelectizeRef) {
+ transformedGroup = {
+ ...transformedGroup,
+ peer_groups: {
+ values: this.getSelectizeValuesToSave(
+ transformedGroup.peer_groups ? transformedGroup.peer_groups.values : [],
+ peerGroupsSelectizeRef,
+ ),
+ },
+ };
+ }
+ if (childGroupsSelectizeRef) {
+ transformedGroup = {
+ ...transformedGroup,
+ child_groups: {
+ values: this.getSelectizeValuesToSave(
+ transformedGroup.child_groups ? transformedGroup.child_groups.values : [],
+ childGroupsSelectizeRef,
+ ),
+ },
+ };
+ }
+ if (addMembersSelectizeRef) {
+ transformedGroup = {
+ ...transformedGroup,
+ members: {
+ values: this.getSelectizeValuesToSave(
+ this.state.unmodifiedGroup.members ? this.state.unmodifiedGroup.members.values : [],
+ null,
+ transformedGroup.members ? transformedGroup.members.values : [],
+ ),
+ },
+ };
+ }
}
return transformedGroup;
};
- onSaveGroup = () => {
+ onSaveGroup = (quickAction = {}) => {
this.setState(
{
nameRequired: false,
@@ -1940,7 +2107,7 @@ class GroupDetailScreen extends React.Component {
Keyboard.dismiss();
if (this.state.group.title) {
const { unmodifiedGroup } = this.state;
- const group = this.transformGroupObject(this.state.group);
+ const group = this.transformGroupObject(this.state.group, quickAction);
let groupToSave = {
...sharedTools.diff(unmodifiedGroup, group),
title: this.state.group.title,
@@ -2001,38 +2168,81 @@ class GroupDetailScreen extends React.Component {
}
};
+ openCommentDialog = (comment, deleteComment = false) => {
+ this.setState({
+ commentDialog: {
+ toggle: true,
+ data: comment,
+ delete: deleteComment,
+ },
+ });
+ };
+
+ onCloseCommentDialog() {
+ this.setState({
+ commentDialog: {
+ toggle: false,
+ data: {},
+ delete: false,
+ },
+ });
+ }
+
+ onUpdateComment(commentData) {
+ this.props.saveComment(
+ this.props.userData.domain,
+ this.props.userData.token,
+ this.state.group.ID,
+ commentData,
+ );
+ this.onCloseCommentDialog();
+ }
+
+ onDeleteComment(commentData) {
+ this.props.deleteComment(
+ this.props.userData.domain,
+ this.props.userData.token,
+ this.state.group.ID,
+ commentData.ID,
+ );
+ this.onCloseCommentDialog();
+ }
+
showAssignedUser = () => {
const foundUser = [...this.state.users, ...this.state.assignedToContacts].find(
(user) => user.key === this.state.group.assigned_to.key,
);
return (
-
- {foundUser.label}
-
+ this.goToContactDetailScreen(foundUser.key, foundUser.label)}>
+
+ {foundUser.label}
+
+
);
};
- goToGroupDetailScreen = (groupData) => {
- const { navigation } = this.props;
+ goToGroupDetailScreen = (groupID, name) => {
+ let { navigation } = this.props;
/* eslint-disable */
- const { params } = navigation.state;
- const { ID, title } = this.state.group;
- params.previousList.push({
- groupId: ID,
- onlyView: true,
- groupName: title,
- });
+ // Save new group in 'previousGroups' array
+ if (!this.props.previousGroups.find((previousGroup) => previousGroup.groupId === groupID)) {
+ // Add contact to 'previousGroups' array on creation
+ this.props.updatePrevious([
+ ...this.props.previousGroups,
+ {
+ groupId: groupID,
+ onlyView: true,
+ groupName: name,
+ },
+ ]);
+ }
navigation.push('GroupDetail', {
- ...params, // previousList, onGoBack()
- groupId: groupData.value,
+ groupId: groupID,
onlyView: true,
- groupName: groupData.name,
- backButtonTap: this.backButtonTap.bind(this),
- onBackFromSameScreen: this.onBackFromSameScreen.bind(this),
+ groupName: name,
+ afterBack: () => this.afterBack(),
});
/* eslint-enable */
};
@@ -2057,25 +2267,43 @@ class GroupDetailScreen extends React.Component {
);
noCommentsRender = () => (
-
-
-
-
-
- {i18n.t('groupDetailScreen.noGroupCommentPlacheHolder')}
-
-
- {i18n.t('groupDetailScreen.noGroupCommentPlacheHolder1')}
-
- {!this.props.isConnected && (
-
- {i18n.t('groupDetailScreen.noGroupCommentPlacheHolderOffline')}
-
- )}
-
+ this.onRefreshCommentsActivities(this.state.group.ID, true)}
+ />
+ }>
+
+
+
+
+
+
+
+ {i18n.t('groupDetailScreen.noGroupCommentPlacheHolder')}
+
+
+
+
+ {i18n.t('groupDetailScreen.noGroupCommentPlacheHolder1')}
+
+
+ {!this.props.isConnected && (
+
+
+ {i18n.t('groupDetailScreen.noGroupCommentPlacheHolderOffline')}
+
+
+ )}
+
+
+
);
detailView = () => (
+ /*_viewable_*/
{this.state.onlyView ? (
@@ -2088,18 +2316,26 @@ class GroupDetailScreen extends React.Component {
/>
}>
-
- {this.props.groupSettings.fields.group_status.name}
-
+
+
+
+
+
+
+ {this.props.groupSettings.fields.group_status.name}
+
+
+
-
+
- {(this.state.group.assigned_to) ? this.showAssignedUser() : null}
+ {this.state.group.assigned_to ? this.showAssignedUser() : null}
{this.props.groupSettings.fields.assigned_to.name}
@@ -2149,31 +2389,35 @@ class GroupDetailScreen extends React.Component {
-
+
+
+
-
+
{this.state.group.coaches ? (
- this.state.group.coaches.values.map((contact, index) =>
+ this.state.group.coaches.values.map((contact, index) => (
this.goToContactDetailScreen(contact.value)}>
-
+ onPress={() => this.goToContactDetailScreen(contact.value, contact.name)}>
+
{contact.name}
- )) : (
-
- )}
+ ))
+ ) : (
+
+ )}
@@ -2195,14 +2439,14 @@ class GroupDetailScreen extends React.Component {
]}>
{this.state.group.location_grid
? this.state.group.location_grid.values
- .map(
- (location) =>
- this.state.geonames.find(
- (geoname) => geoname.value === location.value,
- ).name,
- )
- .filter(String)
- .join(', ')
+ .map(
+ (location) =>
+ this.state.geonames.find(
+ (geoname) => geoname.value === location.value,
+ ).name,
+ )
+ .filter(String)
+ .join(', ')
: ''}
@@ -2225,14 +2469,14 @@ class GroupDetailScreen extends React.Component {
]}>
{this.state.group.people_groups
? this.state.group.people_groups.values
- .map(
- (peopleGroup) =>
- this.state.peopleGroups.find(
- (person) => person.value === peopleGroup.value,
- ).name,
- )
- .filter(String)
- .join(', ')
+ .map(
+ (peopleGroup) =>
+ this.state.peopleGroups.find(
+ (person) => person.value === peopleGroup.value,
+ ).name,
+ )
+ .filter(String)
+ .join(', ')
: ''}
@@ -2267,7 +2511,7 @@ class GroupDetailScreen extends React.Component {
-
+
{this.state.group.start_date
- ? moment(new Date(this.state.group.start_date * 1000)).format('LL')
+ ? moment(new Date(this.state.group.start_date * 1000))
+ .utc()
+ .format('LL')
: ''}
@@ -2289,7 +2535,7 @@ class GroupDetailScreen extends React.Component {
-
+
{this.state.group.church_start_date
- ? moment(new Date(this.state.group.church_start_date * 1000)).format('LL')
+ ? moment(new Date(this.state.group.church_start_date * 1000))
+ .utc()
+ .format('LL')
: ''}
-
-
+
+
{this.props.groupSettings.fields.church_start_date.name}
@@ -2311,7 +2559,7 @@ class GroupDetailScreen extends React.Component {
-
+
{this.state.group.end_date
- ? moment(new Date(this.state.group.end_date * 1000)).format('LL')
+ ? moment(new Date(this.state.group.end_date * 1000))
+ .utc()
+ .format('LL')
: ''}
@@ -2335,149 +2585,131 @@ class GroupDetailScreen extends React.Component {
) : (
-
-
-
- {this.props.groupSettings.fields.group_status.name}
-
-
-
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.group_status.name}
+
+
+
+
+
+
-
- {Object.keys(this.props.groupSettings.fields.group_status.values).map((key) => {
- const optionData = this.props.groupSettings.fields.group_status.values[key];
- return ;
- })}
-
-
-
-
-
-
-
-
-
-
-
- {i18n.t('groupDetailScreen.groupName.label')}
-
-
-
-
-
-
-
-
-
-
-
+ {Object.keys(this.props.groupSettings.fields.group_status.values).map((key) => {
+ const optionData = this.props.groupSettings.fields.group_status.values[key];
+ return ;
+ })}
+
+
+
+
+
+
+
+
+
+
+
+ {i18n.t('groupDetailScreen.groupName.label')}
+
+
+
+
+
+
+
+
+
+
+
-
-
- {this.state.nameRequired ? (
-
- {i18n.t('groupDetailScreen.groupName.error')}
-
- ) : null}
+ : null
+ }>
+
-
- {
- this.updateShowAssignedToModal(true);
- }}>
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.assigned_to.name}
-
-
-
-
-
-
-
-
-
-
-
- {this.renderPickerItems([...this.state.users, ...this.state.assignedToContacts])}
-
-
-
-
+ {this.state.nameRequired ? (
+
+ {i18n.t('groupDetailScreen.groupName.error')}
+
+ ) : null}
+
+
+ {
+ this.updateShowAssignedToModal(true);
+ }}>
-
+
- {this.props.groupSettings.fields.coaches.name}
+ {this.props.groupSettings.fields.assigned_to.name}
@@ -2485,382 +2717,427 @@ class GroupDetailScreen extends React.Component {
-
- {
- coachesSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.groupCoachContacts, ...this.state.usersContacts]}
- selectedItems={this.getSelectizeItems(
- this.state.group.coaches,
- [...this.state.groupCoachContacts, ...this.state.usersContacts],
- )}
- textInputProps={{
- placeholder: i18n.t('groupDetailScreen.selectCoaches'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+ {this.renderPickerItems([
+ ...this.state.users,
+ ...this.state.assignedToContacts,
+ ])}
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.coaches.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ coachesSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.groupCoachContacts, ...this.state.usersContacts]}
+ selectedItems={this.getSelectizeItems(this.state.group.coaches, [
+ ...this.state.groupCoachContacts,
+ ...this.state.usersContacts,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('groupDetailScreen.selectCoaches'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundCoachIndex = this.state.groupCoachContacts.findIndex(
- (coach) => coach.value === id
- );
- if (foundCoachIndex > -1) {
- // Remove coach from list
- const groupCoachContacts = [...this.state.groupCoachContacts];
- groupCoachContacts.splice(foundCoachIndex, 1);
- this.setState({
- groupCoachContacts: [...groupCoachContacts],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- keyboardShouldPersistTaps
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.location_grid.name}
-
-
-
-
-
-
-
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundCoachIndex = this.state.groupCoachContacts.findIndex(
+ (coach) => coach.value === id,
+ );
+ if (foundCoachIndex > -1) {
+ // Remove coach from list
+ const groupCoachContacts = [...this.state.groupCoachContacts];
+ groupCoachContacts.splice(foundCoachIndex, 1);
+ this.setState({
+ groupCoachContacts: [...groupCoachContacts],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
/>
-
-
-
- {
- geonamesSelectizeRef = selectize;
- }}
- itemId="value"
- items={this.state.foundGeonames}
- selectedItems={this.getSelectizeItems(
- this.state.group.location_grid,
- this.state.geonames,
- )}
- textInputProps={{
- placeholder: i18n.t('groupDetailScreen.selectLocations'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.location_grid.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ geonamesSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={this.state.foundGeonames}
+ selectedItems={this.getSelectizeItems(
+ this.state.group.location_grid,
+ this.state.geonames,
+ )}
+ textInputProps={{
+ placeholder: i18n.t('groupDetailScreen.selectLocations'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
-
- )}
- filterOnKey="name"
- keyboardShouldPersistTaps
- inputContainerStyle={styles.selectizeField}
- textInputProps={{
- onChangeText: this.searchLocationsDelayed,
- }}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.people_groups.name}
-
-
-
-
-
-
-
-
-
-
- {
- peopleGroupsSelectizeRef = selectize;
- }}
- itemId="value"
- items={this.state.peopleGroups}
- selectedItems={this.getSelectizeItems(
- this.state.group.people_groups,
- this.state.peopleGroups,
- )}
- textInputProps={{
- placeholder: i18n.t('global.selectPeopleGroups'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+
+ )}
+ filterOnKey="name"
+ keyboardShouldPersistTaps
+ inputContainerStyle={styles.selectizeField}
+ textInputProps={{
+ onChangeText: this.searchLocationsDelayed,
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.people_groups.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ peopleGroupsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={this.state.peopleGroups}
+ selectedItems={this.getSelectizeItems(
+ this.state.group.people_groups,
+ this.state.peopleGroups,
+ )}
+ textInputProps={{
+ placeholder: i18n.t('global.selectPeopleGroups'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
-
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+
+ )}
+ filterOnKey="name"
+ keyboardShouldPersistTaps
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.channels.address.label}
+
+
+
+
+
+
+ {this.state.group.contact_address ? (
+ this.state.group.contact_address.map((address, index) =>
+ !address.delete ? (
+
+
+
+
+
+
+
+ {
+ this.onAddressFieldChange(value, index, address.key, this);
+ }}
+ style={styles.groupTextField}
/>
- )}
- filterOnKey="name"
- keyboardShouldPersistTaps
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.channels.address.label}
-
-
-
+
+
+ {
+ this.onRemoveAddressField(index, this);
+ }}
+ />
+
+
+ ) : null,
+ )
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.start_date.name}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.church_start_date.name}
+
+
+
+
+
+
-
-
- {this.state.group.contact_address ? (
- this.state.group.contact_address.map((address, index) =>
- !address.delete ? (
-
-
-
-
-
-
-
- {
- this.onAddressFieldChange(value, index, address.key, this);
- }}
- style={styles.groupTextField}
- />
-
-
- {
- this.onRemoveAddressField(index, this);
- }}
- />
-
-
- ) : null,
- )
- ) : (
-
- )}
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.start_date.name}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.church_start_date.name}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.end_date.name}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.end_date.name}
+
+
+
+
+
+
+
-
-
-
-
- )}
+
+
+
+
+
+
+
+
+ )}
);
progressView = () => (
+ /*_viewable_*/
{this.state.onlyView ? (
@@ -2872,7 +3149,7 @@ class GroupDetailScreen extends React.Component {
onRefresh={() => this.onRefresh(this.state.group.ID)}
/>
}>
-
+
@@ -2885,8 +3162,8 @@ class GroupDetailScreen extends React.Component {
]}>
{this.state.group.group_type
? this.props.groupSettings.fields.group_type.values[
- this.state.group.group_type
- ].label
+ this.state.group.group_type
+ ].label
: ''}
@@ -2897,66 +3174,78 @@ class GroupDetailScreen extends React.Component {
-
- {this.props.groupSettings.fields.health_metrics.name}
-
-
- {this.renderHealthMilestones()}
- {this.renderCustomHealthMilestones()}
-
-
- ) : (
-
-
-
-
-
-
-
+
+
+
-
- {this.props.groupSettings.fields.group_type.name}
+
+ {this.props.groupSettings.fields.health_metrics.name}
-
-
-
-
-
-
-
-
- {Object.keys(this.props.groupSettings.fields.group_type.values).map((key) => {
- const optionData = this.props.groupSettings.fields.group_type.values[key];
- return ;
- })}
-
-
-
-
- {this.props.groupSettings.fields.health_metrics.name}
-
{this.renderHealthMilestones()}
{this.renderCustomHealthMilestones()}
-
- )}
+
+
+ ) : (
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.group_type.name}
+
+
+
+
+
+
+
+
+
+
+
+ {Object.keys(this.props.groupSettings.fields.group_type.values).map((key) => {
+ const optionData = this.props.groupSettings.fields.group_type.values[key];
+ return ;
+ })}
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.health_metrics.name}
+
+
+
+
+ {this.renderHealthMilestones()}
+ {this.renderCustomHealthMilestones()}
+
+ )}
);
@@ -3001,83 +3290,63 @@ class GroupDetailScreen extends React.Component {
}
commentsView = () => (
+ /*_viewable_*/
- {this.state.comments.length == 0 &&
- this.state.activities.length == 0 &&
- !this.state.loadComments &&
- !this.state.loadActivities &&
- this.noCommentsRender()}
- {
- commentsFlatList = flatList;
- }}
- data={this.getCommentsAndActivities()}
- extraData={!this.state.loadMoreComments || !this.state.loadMoreActivities}
- inverted
- ItemSeparatorComponent={() => (
-
- )}
- keyExtractor={(item, index) => String(index)}
- renderItem={(item) => {
- const commentOrActivity = item.item;
- return this.renderActivityOrCommentRow(commentOrActivity);
- }}
- refreshControl={
- this.onRefreshCommentsActivities(this.state.group.ID)}
- />
- }
- onScroll={({ nativeEvent }) => {
- const {
- loadMoreComments,
- commentsOffset,
- loadMoreActivities,
- activitiesOffset,
- } = this.state;
- const fL = nativeEvent;
- const contentOffsetY = fL.contentOffset.y;
- const layoutMeasurementHeight = fL.layoutMeasurement.height;
- const contentSizeHeight = fL.contentSize.height;
- const heightOffsetSum = layoutMeasurementHeight + contentOffsetY;
- const distanceToStart = contentSizeHeight - heightOffsetSum;
-
- if (distanceToStart < 100) {
- if (!loadMoreComments) {
- if (commentsOffset < this.state.totalComments) {
- this.setState(
- {
- loadMoreComments: true,
- },
- () => {
- this.getGroupComments(this.state.group.ID);
- },
- );
- }
- }
- if (!loadMoreActivities) {
- if (activitiesOffset < this.state.totalActivities) {
- this.setState(
- {
- loadMoreActivities: true,
- },
- () => {
- this.getGroupActivities(this.state.group.ID);
- },
- );
- }
- }
+ {this.state.comments.data.length == 0 &&
+ this.state.activities.data.length == 0 &&
+ !this.state.loadComments &&
+ !this.state.loadActivities ? (
+ this.noCommentsRender()
+ ) : (
+ {
+ commentsFlatList = flatList;
+ }}
+ data={this.getCommentsAndActivities()}
+ extraData={!this.state.loadMoreComments || !this.state.loadMoreActivities}
+ inverted
+ ItemSeparatorComponent={() => (
+
+ )}
+ keyExtractor={(item, index) => String(index)}
+ renderItem={(item) => {
+ const commentOrActivity = item.item;
+ return this.renderActivityOrCommentRow(commentOrActivity);
+ }}
+ refreshControl={
+ this.onRefreshCommentsActivities(this.state.group.ID, true)}
+ />
}
- }}
- />
+ onScroll={({ nativeEvent }) => {
+ sharedTools.onlyExecuteLastCall(
+ {},
+ () => {
+ const flatList = nativeEvent;
+ const contentOffsetY = flatList.contentOffset.y;
+ const layoutMeasurementHeight = flatList.layoutMeasurement.height;
+ const contentSizeHeight = flatList.contentSize.height;
+ const heightOffsetSum = layoutMeasurementHeight + contentOffsetY;
+ const distanceToStart = contentSizeHeight - heightOffsetSum;
+ if (distanceToStart < 100) {
+ this.getGroupComments(this.state.group.ID);
+ this.getGroupActivities(this.state.group.ID);
+ }
+ },
+ 500,
+ );
+ }}
+ />
+ )}
leader.value === membersGroup.value,
- )
+ this.state.group.leaders.values.find(
+ (leader) => leader.value === membersGroup.value,
+ )
? styles.membersIconActive
: styles.membersIconInactive,
]}
@@ -3172,7 +3441,7 @@ class GroupDetailScreen extends React.Component {
this.goToContactDetailScreen(membersGroup.value)}
+ onPress={() => this.goToContactDetailScreen(membersGroup.value, membersGroup.name)}
key={membersGroup.value}
style={{ marginTop: 'auto', marginBottom: 'auto' }}>
) : (
-
-
- this.onSetLeader(membersGroup)}
- key={membersGroup.value}>
- leader.value === membersGroup.value,
- )
- ? styles.membersIconActive
- : styles.membersIconInactive,
- ]}
- />
-
-
-
- this.goToContactDetailScreen(membersGroup.value)}
- key={membersGroup.value}
- style={{ marginTop: 'auto', marginBottom: 'auto' }}>
-
- {membersGroup.name}
-
-
-
-
- this.onRemoveMember(membersGroup)}
- key={membersGroup.value}>
-
-
-
-
- )}
+
+
+ this.onSetLeader(membersGroup)}
+ key={membersGroup.value}>
+ leader.value === membersGroup.value && !leader.delete,
+ )
+ ? styles.membersIconActive
+ : styles.membersIconInactive,
+ ]}
+ />
+
+
+
+ this.goToContactDetailScreen(membersGroup.value, membersGroup.name)}
+ key={membersGroup.value}
+ style={{ marginTop: 'auto', marginBottom: 'auto' }}>
+
+ {membersGroup.name}
+
+
+
+
+ this.onRemoveMember(membersGroup)}
+ key={membersGroup.value}>
+
+
+
+
+ )}
);
membersView = () => {
+ /*_viewable_*/
return this.state.onlyView ? (
) : (
-
-
-
-
- {i18n.t('global.membersActivity')}
-
- this.membersRow(item.item)}
- ItemSeparatorComponent={this.flatListItemSeparator}
- />
-
-
-
-
-
-
- {
- addMembersSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.membersContacts, ...this.state.usersContacts].filter(
- (userContact) =>
- this.state.group.members &&
- !this.state.group.members.values.find(
- (member) => member.value === userContact.value,
- ),
- )}
- selectedItems={[]}
- textInputProps={{
- placeholder: i18n.t('groupDetailScreen.addMember'),
- leftIcon: { type: 'Entypo', name: 'add-user' },
- }}
- renderRow={(id, onPress, item) => (
- this.onAddMember(item)}
+
+
+
+
+ {i18n.t('global.membersActivity')}
+
+ this.membersRow(item.item)}
+ ItemSeparatorComponent={this.flatListItemSeparator}
+ />
+
+
+
+
+
+
+ {
+ addMembersSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.membersContacts, ...this.state.usersContacts].filter(
+ (userContact) =>
+ this.state.group.members &&
+ !this.state.group.members.values.find(
+ (member) => member.value === userContact.value,
+ ),
+ )}
+ selectedItems={[]}
+ textInputProps={{
+ placeholder: i18n.t('groupDetailScreen.addMember'),
+ leftIcon: { type: 'Entypo', name: 'add-user' },
+ }}
+ renderRow={(id, onPress, item) => (
+ this.onAddMember(item)}
+ style={{
+ paddingVertical: 8,
+ paddingHorizontal: 10,
+ }}>
+
-
-
- {item.name}
-
-
- {' '}
- (#
- {id})
-
-
-
- )}
- filterOnKey="name"
- keyboardShouldPersistTaps
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
- );
+ {item.name}
+
+
+ {' '}
+ (#
+ {id})
+
+
+
+ )}
+ filterOnKey="name"
+ keyboardShouldPersistTaps
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+
+
+ );
};
groupsView = () => (
+ /*_viewable_*/
{this.state.onlyView ? (
@@ -3372,13 +3643,15 @@ class GroupDetailScreen extends React.Component {
this.goToGroupDetailScreen(parentGroup)}>
+ onPress={() =>
+ this.goToGroupDetailScreen(parentGroup.value, parentGroup.name)
+ }>
{Object.prototype.hasOwnProperty.call(parentGroup, 'is_church') &&
- parentGroup.is_church ? (
-
- ) : (
-
- )}
+ parentGroup.is_church ? (
+
+ ) : (
+
+ )}
{parentGroup.name}
@@ -3392,8 +3665,8 @@ class GroupDetailScreen extends React.Component {
))
) : (
-
- )}
+
+ )}
@@ -3417,13 +3690,13 @@ class GroupDetailScreen extends React.Component {
this.goToGroupDetailScreen(peerGroup)}>
+ onPress={() => this.goToGroupDetailScreen(peerGroup.value, peerGroup.name)}>
{Object.prototype.hasOwnProperty.call(peerGroup, 'is_church') &&
- peerGroup.is_church ? (
-
- ) : (
-
- )}
+ peerGroup.is_church ? (
+
+ ) : (
+
+ )}
{peerGroup.name}
@@ -3437,8 +3710,8 @@ class GroupDetailScreen extends React.Component {
))
) : (
-
- )}
+
+ )}
@@ -3460,13 +3733,15 @@ class GroupDetailScreen extends React.Component {
this.goToGroupDetailScreen(childGroup)}>
+ onPress={() =>
+ this.goToGroupDetailScreen(childGroup.value, childGroup.name)
+ }>
{Object.prototype.hasOwnProperty.call(childGroup, 'is_church') &&
- childGroup.is_church ? (
-
- ) : (
-
- )}
+ childGroup.is_church ? (
+
+ ) : (
+
+ )}
{childGroup.name}
@@ -3480,307 +3755,307 @@ class GroupDetailScreen extends React.Component {
))
) : (
-
- )}
-
-
-
-
-
-
- ) : (
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.parent_groups.name}
-
-
-
-
-
-
-
-
-
-
- {
- parentGroupsSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.groups, ...this.state.parentGroups]}
- selectedItems={this.getSelectizeItems(
- this.state.group.parent_groups,
- [...this.state.groups, ...this.state.parentGroups],
- )}
- textInputProps={{
- placeholder: i18n.t('groupDetailScreen.searchGroups'),
- }}
- renderRow={(id, onPress, item) => (
-
-
-
- {item.name}
-
-
- {' '}
- (#
- {id})
-
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundParentGroupIndex = this.state.parentGroups.findIndex(
- (parentGroup) => parentGroup.value === id
- );
- if (foundParentGroupIndex > -1) {
- // Remove parent group from list
- const parentGroups = [...this.state.parentGroups];
- parentGroups.splice(foundParentGroupIndex, 1);
- this.setState({
- parentGroups: [...parentGroups],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- keyboardShouldPersistTaps
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.peer_groups.name}
-
-
+
+ )}
+
-
-
-
-
-
-
-
- {
- peerGroupsSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.groups, this.state.peerGroups]}
- selectedItems={this.getSelectizeItems(
- this.state.group.peer_groups,
- [...this.state.groups, this.state.peerGroups],
- )}
- textInputProps={{
- placeholder: i18n.t('groupDetailScreen.searchPeerGroups'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.parent_groups.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ parentGroupsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.groups, ...this.state.parentGroups]}
+ selectedItems={this.getSelectizeItems(this.state.group.parent_groups, [
+ ...this.state.groups,
+ ...this.state.parentGroups,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('groupDetailScreen.searchGroups'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundPeerGroupIndex = this.state.peerGroups.findIndex(
- (peerGroup) => peerGroup.value === id
- );
- if (foundPeerGroupIndex > -1) {
- // Remove peer group from list
- const peerGroups = [...this.state.peerGroups];
- peerGroups.splice(foundPeerGroupIndex, 1);
- this.setState({
- peerGroups: [...peerGroups],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- keyboardShouldPersistTaps
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
-
-
-
-
-
-
- {this.props.groupSettings.fields.child_groups.name}
-
-
-
-
-
-
-
-
-
-
- {
- childGroupsSelectizeRef = selectize;
- }}
- itemId="value"
- items={[...this.state.groups, ...this.state.childGroups]}
- selectedItems={this.getSelectizeItems(
- this.state.group.child_groups,
- [...this.state.groups, ...this.state.childGroups],
- )}
- textInputProps={{
- placeholder: i18n.t('groupDetailScreen.searchChildGroups'),
- }}
- renderRow={(id, onPress, item) => (
-
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundParentGroupIndex = this.state.parentGroups.findIndex(
+ (parentGroup) => parentGroup.value === id,
+ );
+ if (foundParentGroupIndex > -1) {
+ // Remove parent group from list
+ const parentGroups = [...this.state.parentGroups];
+ parentGroups.splice(foundParentGroupIndex, 1);
+ this.setState({
+ parentGroups: [...parentGroups],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
+ />
+ )}
+ filterOnKey="name"
+ keyboardShouldPersistTaps
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.peer_groups.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ peerGroupsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.groups, this.state.peerGroups]}
+ selectedItems={this.getSelectizeItems(this.state.group.peer_groups, [
+ ...this.state.groups,
+ this.state.peerGroups,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('groupDetailScreen.searchPeerGroups'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
-
-
- {item.name}
-
-
- {' '}
+ {item.name}
+
+
+ {' '}
(#
{id})
-
-
- )}
- renderChip={(id, onClose, item, style, iconStyle) => (
- {
- let foundChildGroupIndex = this.state.childGroups.findIndex(
- (childGroup) => childGroup.value === id
- );
- if (foundChildGroupIndex > -1) {
- // Remove child group from list
- const childGroups = [...this.state.childGroups];
- childGroups.splice(foundChildGroupIndex, 1);
- this.setState({
- childGroups: [...childGroups],
- });
- }
- onClose(props);
- }}
- text={item.name}
- style={style}
- />
- )}
- filterOnKey="name"
- keyboardShouldPersistTaps
- inputContainerStyle={styles.selectizeField}
- />
-
-
-
-
- )}
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundPeerGroupIndex = this.state.peerGroups.findIndex(
+ (peerGroup) => peerGroup.value === id,
+ );
+ if (foundPeerGroupIndex > -1) {
+ // Remove peer group from list
+ const peerGroups = [...this.state.peerGroups];
+ peerGroups.splice(foundPeerGroupIndex, 1);
+ this.setState({
+ peerGroups: [...peerGroups],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
+ />
+ )}
+ filterOnKey="name"
+ keyboardShouldPersistTaps
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+
+
+
+
+
+
+ {this.props.groupSettings.fields.child_groups.name}
+
+
+
+
+
+
+
+
+
+
+ {
+ childGroupsSelectizeRef = selectize;
+ }}
+ itemId="value"
+ items={[...this.state.groups, ...this.state.childGroups]}
+ selectedItems={this.getSelectizeItems(this.state.group.child_groups, [
+ ...this.state.groups,
+ ...this.state.childGroups,
+ ])}
+ textInputProps={{
+ placeholder: i18n.t('groupDetailScreen.searchChildGroups'),
+ }}
+ renderRow={(id, onPress, item) => (
+
+
+
+ {item.name}
+
+
+ {' '}
+ (#
+ {id})
+
+
+
+ )}
+ renderChip={(id, onClose, item, style, iconStyle) => (
+ {
+ let foundChildGroupIndex = this.state.childGroups.findIndex(
+ (childGroup) => childGroup.value === id,
+ );
+ if (foundChildGroupIndex > -1) {
+ // Remove child group from list
+ const childGroups = [...this.state.childGroups];
+ childGroups.splice(foundChildGroupIndex, 1);
+ this.setState({
+ childGroups: [...childGroups],
+ });
+ }
+ onClose(props);
+ }}
+ text={item.name}
+ style={style}
+ />
+ )}
+ filterOnKey="name"
+ keyboardShouldPersistTaps
+ inputContainerStyle={styles.selectizeField}
+ />
+
+
+
+
+ )}
);
@@ -4256,7 +4531,9 @@ class GroupDetailScreen extends React.Component {
renderPickerItems = (items) =>
items.map((item) => {
- return ;
+ return (
+
+ );
});
renderCustomHealthMilestones() {
@@ -4369,6 +4646,101 @@ class GroupDetailScreen extends React.Component {
this.props.searchLocations(this.props.userData.domain, this.props.userData.token, queryText);
};
+ onSaveQuickAction = (quickActionPropertyName) => {
+ let newActionValue = this.state.group[quickActionPropertyName]
+ ? parseInt(this.state.group[quickActionPropertyName], 10) + 1
+ : 1;
+ /*
+ if (this.props.isConnected) {
+ // ONLINE mode
+ this.onSaveGroup({
+ [quickActionPropertyName]: newActionValue,
+ });
+ } else {
+ // OFFLINE mode
+ }
+ */
+ var comment = '';
+ switch (quickActionPropertyName) {
+ case 'quick_button_meeting_scheduled':
+ comment = i18n.t('groupDetailScreen.fab.quick_button_meeting_scheduled');
+ break;
+ case 'quick_button_meeting_postponed':
+ comment = i18n.t('groupDetailScreen.fab.quick_button_meeting_postponed');
+ break;
+ case 'quick_button_meeting_complete':
+ comment = i18n.t('groupDetailScreen.fab.quick_button_meeting_complete');
+ break;
+ default:
+ comment = '';
+ }
+ // TODO: temporarily save a Comment until supported by D.T as an Activity w/ count
+ if (comment != '') {
+ this.props.saveComment(
+ this.props.userData.domain,
+ this.props.userData.token,
+ this.state.group.ID,
+ {
+ comment,
+ },
+ );
+ // TODO: saveComment doesn't display Toast on normal `Comments and Activities` tabView, so we mock it
+ toastSuccess.show(
+
+ {i18n.t('global.success.save')}
+ ,
+ 3000,
+ );
+ }
+ };
+
+ /*
+ onMeetingComplete = () => {
+ // determine whether there is an existing 'meeting_complete' questionnaire,
+ // if so, proxy from Attendance to Questionnaire, else back to GroupDetails
+ var isQuestionnaireEnabled = false;
+ var q_id = null;
+ // loop thru all (active) questionnaires, and check whether 'group'->'meeting_complete' is enabled
+ this.props.questionnaires.map((questionnaire) => {
+ if (
+ questionnaire.trigger_type == 'group' &&
+ questionnaire.trigger_value == 'meeting_complete'
+ ) {
+ isQuestionnaireEnabled = true;
+ q_id = questionnaire.id;
+ }
+ });
+ /*
+ this.props.navigation.navigate(
+ NavigationActions.navigate({
+ routeName: 'Attendance',
+ action: NavigationActions.navigate({
+ routeName: 'Attendance',
+ params: {
+ userData: this.props.userData,
+ group: this.state.group,
+ q_id,
+ },
+ }),
+ }),
+ );
+ this.props.navigation.navigate(
+ NavigationActions.navigate({
+ routeName: 'Questionnaire',
+ action: NavigationActions.navigate({
+ routeName: 'Question',
+ params: {
+ userData: this.props.userData,
+ group: this.state.group,
+ title: this.state.group.title,
+ q_id,
+ },
+ }),
+ }),
+ );
+ };
+ */
+
render() {
const successToast = (
+ {this.state.onlyView && this.state.tabViewConfig.index != 2 && (
+
+ active ? (
+
+ ) : (
+
+ )
+ }
+ degrees={0}
+ activeOpacity={0}
+ bgColor="rgba(0,0,0,0.5)"
+ nativeFeedbackRippleColor="rgba(0,0,0,0)">
+ {
+ this.onSaveQuickAction('quick_button_meeting_scheduled');
+ }}
+ size={40}
+ nativeFeedbackRippleColor="rgba(0,0,0,0)"
+ textStyle={{ color: Colors.tintColor, fontSize: 15 }}
+ textContainerStyle={{ height: 'auto' }}>
+
+
+ {
+ //this.onMeetingComplete();
+ this.onSaveQuickAction('quick_button_meeting_complete');
+ }}
+ size={40}
+ nativeFeedbackRippleColor="rgba(0,0,0,0)"
+ textStyle={{ color: Colors.tintColor, fontSize: 15 }}
+ textContainerStyle={{ height: 'auto' }}>
+
+
+ {
+ this.onSaveQuickAction('quick_button_meeting_postponed');
+ }}
+ size={40}
+ nativeFeedbackRippleColor="rgba(0,0,0,0)"
+ textStyle={{ color: Colors.tintColor, fontSize: 15 }}
+ textContainerStyle={{ height: 'auto' }}>
+
+
+
+ )}
+ {this.state.commentDialog.toggle ? (
+
+
+
+
+
+ {this.state.commentDialog.delete ? (
+
+
+
+ {i18n.t('global.delete')}
+
+
+
+
+ {this.state.commentDialog.data.content}
+
+
+
+ ) : (
+
+
+
+
+ {i18n.t('global.edit')}
+
+
+
+ {
+ this.setState((prevState) => ({
+ commentDialog: {
+ ...prevState.commentDialog,
+ data: {
+ ...prevState.commentDialog.data,
+ content: value,
+ },
+ },
+ }));
+ }}
+ style={[
+ styles.groupTextField,
+ { height: 'auto', minHeight: 50 },
+ ]}
+ />
+
+
+
+ )}
+
+
+
+ {this.state.commentDialog.delete ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ ) : null}
) : (
-
- {!this.props.isConnected && this.offlineBarRender()}
-
-
-
-
+
+ {!this.props.isConnected && this.offlineBarRender()}
+
+
+
+
+
+
+
+
+
+
{i18n.t('groupDetailScreen.groupName.label')}
-
-
+
+
-
-
- {this.state.nameRequired ? (
-
- {i18n.t('groupDetailScreen.groupName.error')}
-
- ) : null}
-
-
+ : null
+ }>
+
+
+ {this.state.nameRequired ? (
+
+ {i18n.t('groupDetailScreen.groupName.error')}
+
+ ) : null}
+
+
+
+
+
+
+
+
{this.props.groupSettings.fields.group_type.name}
-
-
-
- {Object.keys(this.props.groupSettings.fields.group_type.values).map(
- (key) => {
- const optionData = this.props.groupSettings.fields.group_type.values[
- key
- ];
- return ;
- },
- )}
-
-
-
-
-
- )}
+
+
+
+
+ {Object.keys(this.props.groupSettings.fields.group_type.values).map(
+ (key) => {
+ const optionData = this.props.groupSettings.fields.group_type.values[
+ key
+ ];
+ return ;
+ },
+ )}
+
+
+
+
+
+ )}
)}
{successToast}
@@ -4516,13 +5093,7 @@ GroupDetailScreen.propTypes = {
code: PropTypes.any,
message: PropTypes.string,
}),
- newComment: PropTypes.shape({
- ID: PropTypes.string,
- author: PropTypes.string,
- content: PropTypes.string,
- date: PropTypes.string,
- gravatar: PropTypes.string,
- }),
+ newComment: PropTypes.bool,
groupsReducerError: PropTypes.shape({
code: PropTypes.any,
message: PropTypes.string,
@@ -4651,6 +5222,8 @@ const mapStateToProps = (state) => ({
groupsList: state.groupsReducer.groups,
contactsList: state.contactsReducer.contacts,
isRTL: state.i18nReducer.isRTL,
+ previousGroups: state.groupsReducer.previousGroups,
+ previousContacts: state.contactsReducer.previousContacts,
});
const mapDispatchToProps = (dispatch) => ({
@@ -4660,14 +5233,14 @@ const mapDispatchToProps = (dispatch) => ({
getById: (domain, token, groupId) => {
dispatch(getById(domain, token, groupId));
},
- getComments: (domain, token, groupId, offset, limit) => {
- dispatch(getCommentsByGroup(domain, token, groupId, offset, limit));
+ getComments: (domain, token, groupId, pagination) => {
+ dispatch(getCommentsByGroup(domain, token, groupId, pagination));
},
saveComment: (domain, token, groupId, commentData) => {
dispatch(saveComment(domain, token, groupId, commentData));
},
- getActivities: (domain, token, groupId, offset, limit) => {
- dispatch(getActivitiesByGroup(domain, token, groupId, offset, limit));
+ getActivities: (domain, token, groupId, pagination) => {
+ dispatch(getActivitiesByGroup(domain, token, groupId, pagination));
},
getByIdEnd: () => {
dispatch(getByIdEnd());
@@ -4675,6 +5248,18 @@ const mapDispatchToProps = (dispatch) => ({
searchLocations: (domain, token, queryText) => {
dispatch(searchLocations(domain, token, queryText));
},
+ deleteComment: (domain, token, groupId, commentId) => {
+ dispatch(deleteComment(domain, token, groupId, commentId));
+ },
+ loadingFalse: () => {
+ dispatch(loadingFalse());
+ },
+ updatePrevious: (previousGroups) => {
+ dispatch(updatePrevious(previousGroups));
+ },
+ updatePreviousContacts: (previousContacts) => {
+ dispatch(updatePreviousContacts(previousContacts));
+ },
});
export default connect(mapStateToProps, mapDispatchToProps)(GroupDetailScreen);
diff --git a/screens/Group/GroupsScreen.js b/screens/Group/GroupsScreen.js
index f5bad641..652edbc4 100644
--- a/screens/Group/GroupsScreen.js
+++ b/screens/Group/GroupsScreen.js
@@ -8,7 +8,7 @@ import {
StyleSheet,
Text,
Image,
- Platform
+ Platform,
} from 'react-native';
import { Fab, Container } from 'native-base';
import Icon from 'react-native-vector-icons/Ionicons';
@@ -17,16 +17,18 @@ import { Row } from 'react-native-easy-grid';
import PropTypes from 'prop-types';
import { SearchBar } from 'react-native-elements';
import Colors from '../../constants/Colors';
-import { getAll } from '../../store/actions/groups.actions';
+import { getAll, updatePrevious } from '../../store/actions/groups.actions';
import i18n from '../../languages';
import dtIcon from '../../assets/images/dt-icon.png';
import sharedTools from '../../shared';
const styles = StyleSheet.create({
flatListItem: {
- height: 40,
+ height: 40 /* this needs auto sizing */,
backgroundColor: 'white',
margin: 20,
+ marginTop: 10,
+ paddingBottom: 10,
},
groupSubtitle: {
flex: 1,
@@ -186,10 +188,18 @@ class GroupsScreen extends React.Component {
- {group.title}
+
+ {group.title}
+
-
+
{this.props.groupSettings.fields.group_status.values[group.group_status]
? this.props.groupSettings.fields.group_status.values[group.group_status].label
: ''}
@@ -208,7 +218,17 @@ class GroupsScreen extends React.Component {
-
+
);
- onRefresh = (pagination = false) => {
- if (pagination) {
- this.setState(
- (prevState) => ({
- offset: prevState.offset + prevState.limit,
- filtered: false,
- search: '',
- }),
- () => {
- this.props.getAllGroups(
- this.props.userData.domain,
- this.props.userData.token,
- this.state.offset,
- this.state.limit,
- this.state.sort,
- );
- },
- );
- } else {
- this.setState(
- () => ({
- offset: 0,
- filtered: false,
- search: '',
- }),
- () => {
- this.props.getAllGroups(
- this.props.userData.domain,
- this.props.userData.token,
- this.state.offset,
- this.state.limit,
- this.state.sort,
- );
- },
- );
- }
+ onRefresh = (increasePagination = false, returnFromDetail = false) => {
+ let newState = {
+ offset: increasePagination ? this.state.offset + this.state.limit : 0,
+ filtered: false,
+ search: '',
+ searchBarFilter: {
+ ...this.state.searchBarFilter,
+ toggle: false,
+ currentFilter: '',
+ },
+ };
+ this.setState(
+ (prevState) => {
+ return returnFromDetail ? prevState : newState;
+ },
+ () => {
+ this.props.getAllGroups(
+ this.props.userData.domain,
+ this.props.userData.token,
+ this.state.offset,
+ this.state.limit,
+ this.state.sort,
+ );
+ },
+ );
};
goToGroupDetailScreen = (groupData = null) => {
if (groupData) {
+ this.props.updatePrevious([
+ {
+ groupId: parseInt(groupData.ID),
+ onlyView: true,
+ groupName: groupData.title,
+ },
+ ]);
// Detail
this.props.navigation.navigate('GroupDetail', {
groupId: groupData.ID,
onlyView: true,
groupName: groupData.title,
- previousList: [],
- onGoBack: () => this.onRefresh(),
+ onGoBack: () => this.onRefresh(false, true),
});
} else {
+ this.props.updatePrevious([]);
// Create
this.props.navigation.navigate('GroupDetail', {
- previousList: [],
onlyView: true,
- onGoBack: () => this.onRefresh(),
+ onGoBack: () => this.onRefresh(false, true),
});
}
};
@@ -299,7 +314,12 @@ class GroupsScreen extends React.Component {
onChangeText={(text) => this.SearchFilterFunction(text)}
autoCorrect={false}
value={this.state.search}
- containerStyle={[styles.searchBarContainer, Platform.OS == "ios" ? { borderBottomColor: Colors.grayLight, borderBottomWidth: 1 } : { elevation: 5 }]}
+ containerStyle={[
+ styles.searchBarContainer,
+ Platform.OS == 'ios'
+ ? { borderBottomColor: Colors.grayLight, borderBottomWidth: 1 }
+ : { elevation: 5 },
+ ]}
inputContainerStyle={styles.searchBarInput}
/>
{!this.state.haveGroups && this.noGroupsRender()}
@@ -461,6 +481,9 @@ const mapDispatchToProps = (dispatch) => ({
getAllGroups: (domain, token, offset, limit, sort) => {
dispatch(getAll(domain, token, offset, limit, sort));
},
+ updatePrevious: (previousGroups) => {
+ dispatch(updatePrevious(previousGroups));
+ },
});
export default connect(mapStateToProps, mapDispatchToProps)(GroupsScreen);
diff --git a/screens/LoginScreen.js b/screens/LoginScreen.js
index 396a3741..5d1aa4c1 100644
--- a/screens/LoginScreen.js
+++ b/screens/LoginScreen.js
@@ -42,6 +42,7 @@ import {
import { getUsers, getContactFilters } from '../store/actions/users.actions';
import { getContactSettings, getAll as getAllContacts } from '../store/actions/contacts.actions';
import { logout } from '../store/actions/user.actions';
+import { getActiveQuestionnaires } from '../store/actions/questionnaire.actions';
const styles = StyleSheet.create({
container: {
@@ -52,7 +53,7 @@ const styles = StyleSheet.create({
header: {
backgroundColor: Colors.tintColor,
width: '100%',
- paddingTop: 100,
+ padding: 35,
alignItems: 'center',
justifyContent: 'flex-end',
},
@@ -61,7 +62,6 @@ const styles = StyleSheet.create({
width: 250,
resizeMode: 'contain',
padding: 20,
- marginBottom: 20,
},
formContainer: {
alignSelf: 'stretch',
@@ -69,9 +69,9 @@ const styles = StyleSheet.create({
padding: 20,
},
signInButton: {
- marginTop: 20,
+ marginTop: 10,
backgroundColor: Colors.tintColor,
- borderRadius: 2,
+ borderRadius: 10,
},
signInButtonText: {
color: 'white',
@@ -141,7 +141,6 @@ const styles = StyleSheet.create({
},
textBox: {
fontSize: 16,
- height: 45,
paddingRight: 30,
paddingLeft: 8,
paddingVertical: 0,
@@ -567,6 +566,7 @@ class LoginScreen extends React.Component {
this.props.getLocationModifiedDate(this.props.userData.domain, this.props.userData.token);
this.props.getUsers(this.props.userData.domain, this.props.userData.token);
this.props.getContactFilters(this.props.userData.domain, this.props.userData.token);
+ this.props.getActiveQuestionnaires(this.props.userData.domain, this.props.userData.token);
};
getUserInfo = () => {
@@ -713,6 +713,7 @@ class LoginScreen extends React.Component {
iconName="ios-globe"
label={i18n.t('loginScreen.domain.label')}
onChangeText={(text) => this.cleanDomainWiteSpace(text)}
+ textAlign={this.props.i18n.isRTL ? 'right' : 'left'}
autoCapitalize="none"
autoCorrect={false}
value={this.state.domain}
@@ -728,6 +729,7 @@ class LoginScreen extends React.Component {
iconName={Platform.OS === 'ios' ? 'ios-person' : 'md-person'}
label={i18n.t('loginScreen.username.label')}
onChangeText={(text) => this.setState({ username: text })}
+ textAlign={this.props.i18n.isRTL ? 'right' : 'left'}
autoCapitalize="none"
autoCorrect={false}
value={this.state.username}
@@ -1064,5 +1066,8 @@ const mapDispatchToProps = (dispatch) => ({
getContactFilters: (domain, token) => {
dispatch(getContactFilters(domain, token));
},
+ getActiveQuestionnaires: (domain, token) => {
+ dispatch(getActiveQuestionnaires(domain, token));
+ },
});
export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);
diff --git a/screens/NotificationsScreen.js b/screens/NotificationsScreen.js
index a51bfcba..7abef9ff 100644
--- a/screens/NotificationsScreen.js
+++ b/screens/NotificationsScreen.js
@@ -292,7 +292,6 @@ class NotificationsScreen extends React.Component {
[`${prop}Id`]: entityId,
onlyView: true,
[`${prop}Name`]: entityTitle,
- previousList: [],
fromNotificationView: true,
});
};
@@ -333,7 +332,7 @@ class NotificationsScreen extends React.Component {
{moment(notification.date_notified).fromNow() +
- ' | ' +
+ ' ~ ' +
moment(notification.date_notified).format('L')}
diff --git a/screens/QuestionnaireScreen.js b/screens/QuestionnaireScreen.js
index 752aa72d..33d0c6e4 100644
--- a/screens/QuestionnaireScreen.js
+++ b/screens/QuestionnaireScreen.js
@@ -1,6 +1,14 @@
import React, { useState, useEffect, useRef } from 'react';
import { connect, useSelector, useDispatch } from 'react-redux';
-import { ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+import {
+ BackHandler,
+ RefreshControl,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
import Swiper from 'react-native-swiper';
import {
Body,
@@ -14,11 +22,13 @@ import {
Radio,
Right,
} from 'native-base';
+import Toast from 'react-native-easy-toast';
import { Col, Row, Grid } from 'react-native-easy-grid';
import PropTypes from 'prop-types';
import Colors from '../constants/Colors';
import i18n from '../languages';
import {
+ getQuestionnaireById,
resetState,
setQuestion,
submitQuestionnaire,
@@ -218,64 +228,124 @@ const NextButton = ({ currIdx, lastIdx, swipeRight, onSubmit }) => {
);
};
-/*
-const Form = ({ idx, form, handleFormChange }) => {
- // TODO: refactor now that we're not using local state
- const [questions, setQuestions] = useState(form.questions);
- const handleQuestionChange = (question) => {
- const questions_p = questions.map((existing_question) => {
- if (existing_question.seq === question.seq) {
- return question;
- }
- return existing_question;
- });
- setQuestions(questions_p);
- handleFormChange({
- ...form,
- questions: questions_p
- });
- }
- return(
-
- { idx + ". " + form.title }
-
- { questions ? questions.map((question, idx) => (
-
-
-
- )) : (
-
- No Questions
-
- )}
-
-
- )
-}
-*/
-
const Questionnaire = ({ navigation }) => {
const dispatch = useDispatch();
+ const q_id = navigation.getParam('q_id');
+ const userData = navigation.getParam('userData');
+ const domain = userData.domain;
+ const token = userData.token;
+ const user_id = userData.id;
+ const contact_id = navigation.getParam('contact').ID;
+
+ const questionnaireState = useSelector((state) => state.questionnaireReducer);
+ const questionnaire = questionnaireState.questionnaire;
+ const save = questionnaireState.save;
+ const error = questionnaireState.error;
+ if (questionnaire != null) {
+ questionnaire.forms.sort(
+ (a, b) => parseInt(a.seq.replace('.', '')) - parseInt(b.seq.replace('.', '')),
+ );
+ }
+
+ useEffect(() => {
+ dispatch(getQuestionnaireById(domain, token, q_id));
+ }, []);
+
+ useEffect(() => {
+ if (save != null) {
+ toastSaveRef.current.show(
+
+ {i18n.t('global.success.save')}
+ ,
+ 1000,
+ () => {
+ dispatch(resetState());
+ goToContactDetailScreen(navigation);
+ },
+ );
+ }
+ }, [save]);
+
+ useEffect(() => {
+ if (error != null) {
+ toastErrorRef.current.show(
+
+
+ {i18n.t('global.error.code')}
+
+ {error.code}
+
+ {i18n.t('global.error.message')}
+
+ {error.message}
+ ,
+ 3000,
+ () => {
+ dispatch(resetState());
+ },
+ );
+ }
+ }, [error]);
+
/*
useEffect(() => {
- navigation.setParams({
- headerTitle: "Jane Doe" //someVariableThatComesFromExternalCall
- })
+ hardwareBackPressListener = BackHandler.addEventListener('hardwareBackPress', () => {
+ sharedTools.onlyExecuteLastCall(
+ null,
+ () => {
+ this.backButtonTap();
+ },
+ 1000,
+ );
+ return true;
+ });
}, [])
*/
- const questionnaire = useSelector((state) => state.questionnaireReducer.questionnaire);
- questionnaire.forms.sort(
- (a, b) => parseInt(a.seq.replace('.', '')) - parseInt(b.seq.replace('.', '')),
+
+ /*
+ let toastSuccess;
+ const successToast = (
+ {
+ toastSuccess = toast;
+ }}
+ style={{ backgroundColor: Colors.successBackground }}
+ positionValue={250}
+ />
);
+
+ let toastError;
+ const errorToast = (
+ {
+ toastError = toast;
+ }}
+ style={{ backgroundColor: Colors.errorBackground }}
+ positionValue={300}
+ />
+ );
+*/
+
const onSubmit = () => {
// TODO: confirm required fields are selected, or give error feedback
- dispatch(submitQuestionnaire(questionnaire));
+ dispatch(
+ submitQuestionnaire(domain, token, {
+ fields: {
+ q_id,
+ user_id,
+ contact_id,
+ data: JSON.stringify({ questionnaire: questionnaire }),
+ },
+ }),
+ );
};
const swiperRef = useRef(null);
const swipeRight = () => {
// TODO: confirm required fields are selected, or give error feedback
swiperRef.current.scrollBy(1, true);
};
+ const toastSaveRef = useRef();
+ const toastErrorRef = useRef();
return (
{
}
paginationStyle={{ bottom: 30 }}
loop={false}>
- {questionnaire.forms ? (
+ {questionnaire != null && questionnaire.forms ? (
questionnaire.forms.map((form, idx) => (
@@ -330,20 +400,52 @@ const Questionnaire = ({ navigation }) => {
swipeRight={swipeRight}
onSubmit={onSubmit}
/>
+
+
))
) : (
-
- Hello, world!
-
+ }>
+
+
)}
);
};
+const goToContactDetailScreen = (navigation) => {
+ const contactData = navigation.getParam('contact');
+ navigation.navigate('ContactDetail', {
+ contactId: contactData.ID,
+ onlyView: true,
+ contactName: contactData.title,
+ previousList: [],
+ onGoBack: null,
+ });
+};
+
Questionnaire.navigationOptions = ({ navigation }) => {
+ let headerLeft = () => (
+ {
+ goToContactDetailScreen(navigation);
+ }}
+ style={{ paddingLeft: 16, color: '#FFFFFF', paddingRight: 16 }}
+ />
+ );
return {
- title: 'Jane Doe', //navigation.getParam("headerTitle"),
+ title: navigation.getParam('contact').title,
+ headerLeft,
headerStyle: {
backgroundColor: Colors.tintColor,
},
diff --git a/store/actions/contacts.actions.js b/store/actions/contacts.actions.js
index 1a220425..c311aeef 100644
--- a/store/actions/contacts.actions.js
+++ b/store/actions/contacts.actions.js
@@ -45,6 +45,15 @@ export const CONTACTS_GET_SETTINGS_SUCCESS = 'CONTACTS_GET_SETTINGS_SUCCESS';
export const CONTACTS_GET_SETTINGS_RESPONSE = 'CONTACTS_GET_SETTINGS_RESPONSE';
export const CONTACTS_GET_SETTINGS_FAILURE = 'CONTACTS_GET_SETTINGS_FAILURE';
+export const CONTACTS_DELETE_COMMENT = 'CONTACTS_DELETE_COMMENT';
+export const CONTACTS_DELETE_COMMENT_START = 'CONTACTS_DELETE_COMMENT_START';
+export const CONTACTS_DELETE_COMMENT_SUCCESS = 'CONTACTS_DELETE_COMMENT_SUCCESS';
+export const CONTACTS_DELETE_COMMENT_RESPONSE = 'CONTACTS_DELETE_COMMENT_RESPONSE';
+export const CONTACTS_DELETE_COMMENT_FAILURE = 'CONTACTS_DELETE_COMMENT_FAILURE';
+
+export const CONTACTS_LOADING_FALSE = 'CONTACTS_LOADING_FALSE';
+export const CONTACTS_UPDATE_PREVIOUS = 'CONTACTS_UPDATE_PREVIOUS';
+
/*
* Action Creators
*/
@@ -89,14 +98,13 @@ export function getByIdEnd() {
};
}
-export function getCommentsByContact(domain, token, contactId, offset, limit) {
+export function getCommentsByContact(domain, token, contactId, pagination) {
return {
type: CONTACTS_GET_COMMENTS,
domain,
token,
contactId,
- offset,
- limit,
+ pagination,
};
}
@@ -110,14 +118,13 @@ export function saveComment(domain, token, contactId, commentData) {
};
}
-export function getActivitiesByContact(domain, token, contactId, offset, limit) {
+export function getActivitiesByContact(domain, token, contactId, pagination) {
return {
type: CONTACTS_GET_ACTIVITIES,
domain,
token,
contactId,
- offset,
- limit,
+ pagination,
};
}
@@ -128,3 +135,26 @@ export function getContactSettings(domain, token) {
token,
};
}
+
+export function deleteComment(domain, token, contactId, commentId) {
+ return {
+ type: CONTACTS_DELETE_COMMENT,
+ domain,
+ token,
+ contactId,
+ commentId,
+ };
+}
+
+export function loadingFalse() {
+ return {
+ type: CONTACTS_LOADING_FALSE,
+ };
+}
+
+export function updatePrevious(previousContacts) {
+ return {
+ type: CONTACTS_UPDATE_PREVIOUS,
+ previousContacts,
+ };
+}
diff --git a/store/actions/groups.actions.js b/store/actions/groups.actions.js
index eb255336..87ff425b 100644
--- a/store/actions/groups.actions.js
+++ b/store/actions/groups.actions.js
@@ -68,6 +68,15 @@ export const GROUPS_LOCATIONS_MODIFIED_DATE_SUCCESS = 'GROUPS_LOCATIONS_MODIFIED
export const GROUPS_LOCATIONS_MODIFIED_DATE_RESPONSE = 'GROUPS_LOCATIONS_MODIFIED_DATE_RESPONSE';
export const GROUPS_LOCATIONS_MODIFIED_DATE_FAILURE = 'GROUPS_LOCATIONS_MODIFIED_DATE_FAILURE';
+export const GROUPS_DELETE_COMMENT = 'GROUPS_DELETE_COMMENT';
+export const GROUPS_DELETE_COMMENT_START = 'GROUPS_DELETE_COMMENT_START';
+export const GROUPS_DELETE_COMMENT_SUCCESS = 'GROUPS_DELETE_COMMENT_SUCCESS';
+export const GROUPS_DELETE_COMMENT_RESPONSE = 'GROUPS_DELETE_COMMENT_RESPONSE';
+export const GROUPS_DELETE_COMMENT_FAILURE = 'GROUPS_DELETE_COMMENT_FAILURE';
+
+export const GROUPS_LOADING_FALSE = 'GROUPS_LOADING_FALSE';
+export const GROUPS_UPDATE_PREVIOUS = 'GROUPS_UPDATE_PREVIOUS';
+
/**
* Action Creators
*/
@@ -106,14 +115,13 @@ export function getByIdEnd() {
};
}
-export function getCommentsByGroup(domain, token, groupId, offset, limit) {
+export function getCommentsByGroup(domain, token, groupId, pagination) {
return {
type: GROUPS_GET_COMMENTS,
domain,
token,
groupId,
- offset,
- limit,
+ pagination,
};
}
@@ -143,14 +151,13 @@ export function getPeopleGroups(domain, token) {
};
}
-export function getActivitiesByGroup(domain, token, groupId, offset, limit) {
+export function getActivitiesByGroup(domain, token, groupId, pagination) {
return {
type: GROUPS_GET_ACTIVITIES,
domain,
token,
groupId,
- offset,
- limit,
+ pagination,
};
}
@@ -178,3 +185,26 @@ export function getLocationListLastModifiedDate(domain, token) {
token,
};
}
+
+export function deleteComment(domain, token, groupId, commentId) {
+ return {
+ type: GROUPS_DELETE_COMMENT,
+ domain,
+ token,
+ groupId,
+ commentId,
+ };
+}
+
+export function loadingFalse() {
+ return {
+ type: GROUPS_LOADING_FALSE,
+ };
+}
+
+export function updatePrevious(previousGroups) {
+ return {
+ type: GROUPS_UPDATE_PREVIOUS,
+ previousGroups,
+ };
+}
diff --git a/store/actions/questionnaire.actions.js b/store/actions/questionnaire.actions.js
index c9a0436d..55461930 100644
--- a/store/actions/questionnaire.actions.js
+++ b/store/actions/questionnaire.actions.js
@@ -1,13 +1,47 @@
/**
* Action Types
*/
+export const GET_QUESTIONNAIRES_ACTIVE = 'GET_QUESTIONNAIRES_ACTIVE';
+export const GET_QUESTIONNAIRES_ACTIVE_START = 'GET_QUESTIONNAIRES_ACTIVE_START';
+export const GET_QUESTIONNAIRES_ACTIVE_SUCCESS = 'GET_QUESTIONNAIRES_ACTIVE_SUCCESS';
+export const GET_QUESTIONNAIRES_ACTIVE_RESPONSE = 'GET_QUESTIONNAIRES_ACTIVE_RESPONSE';
+export const GET_QUESTIONNAIRES_ACTIVE_FAILURE = 'GET_QUESTIONNAIRES_ACTIVE_FAILURE';
+
+export const GET_QUESTIONNAIRE_BY_ID = 'GET_QUESTIONNAIRE_BY_ID';
+export const GET_QUESTIONNAIRE_BY_ID_START = 'GET_QUESTIONNAIRE_BY_ID_START';
+export const GET_QUESTIONNAIRE_BY_ID_SUCCESS = 'GET_QUESTIONNAIRE_BY_ID_SUCCESS';
+export const GET_QUESTIONNAIRE_BY_ID_RESPONSE = 'GET_QUESTIONNAIRE_BY_ID_RESPONSE';
+export const GET_QUESTIONNAIRE_BY_ID_FAILURE = 'GET_QUESTIONNAIRE_BY_ID_FAILURE';
+
+export const SUBMIT_QUESTIONNAIRE = 'SUBMIT_QUESTIONNAIRE';
+export const SUBMIT_QUESTIONNAIRE_START = 'SUBMIT_QUESTIONNAIRE_START';
+export const SUBMIT_QUESTIONNAIRE_SUCCESS = 'SUBMIT_QUESTIONNAIRE_SUCCESS';
+export const SUBMIT_QUESTIONNAIRE_RESPONSE = 'SUBMIT_QUESTIONNAIRE_RESPONSE';
+export const SUBMIT_QUESTIONNAIRE_FAILURE = 'SUBMIT_QUESTIONNAIRE_FAILURE';
+
export const RESET_STATE = 'RESET_STATE';
export const SET_QUESTION = 'SET_QUESTION';
-export const SUBMIT_QUESTIONNAIRE = 'SUBMIT_QUESTIONNAIRE';
/**
* Action Creators
*/
+export function getActiveQuestionnaires(domain, token) {
+ return {
+ type: GET_QUESTIONNAIRES_ACTIVE,
+ domain,
+ token,
+ };
+}
+
+export function getQuestionnaireById(domain, token, id) {
+ return {
+ type: GET_QUESTIONNAIRE_BY_ID,
+ domain,
+ token,
+ id,
+ };
+}
+
export function resetState() {
return {
type: RESET_STATE,
@@ -21,9 +55,11 @@ export function setQuestion(question) {
};
}
-export function submitQuestionnaire(questionnaire) {
+export function submitQuestionnaire(domain, token, questionnaire) {
return {
type: SUBMIT_QUESTIONNAIRE,
+ domain,
+ token,
questionnaire,
};
}
diff --git a/store/reducers/contacts.reducer.js b/store/reducers/contacts.reducer.js
index 7868f2e4..8d08bb30 100644
--- a/store/reducers/contacts.reducer.js
+++ b/store/reducers/contacts.reducer.js
@@ -7,28 +7,23 @@ const initialState = {
error: null,
contacts: [],
contact: null,
- comments: [],
- newComment: null,
- activities: [],
- totalComments: null,
- totalActivities: null,
+ comments: {},
+ newComment: false,
+ activities: {},
loadingComments: false,
loadingActivities: false,
saved: false,
settings: null,
offset: 0,
+ previousContacts: [],
};
export default function contactsReducer(state = initialState, action) {
let newState = {
...state,
contact: null,
- newComment: null,
+ newComment: false,
error: null,
- comments: null,
- totalComments: null,
- activities: null,
- totalActivities: null,
saved: false,
};
const entities = new Html5Entities();
@@ -62,7 +57,7 @@ export default function contactsReducer(state = initialState, action) {
return;
}
case '[object Number]': {
- if(key === 'ID') {
+ if (key === 'ID') {
mappedContact[key] = value.toString();
} else {
mappedContact[key] = value;
@@ -94,7 +89,7 @@ export default function contactsReducer(state = initialState, action) {
// assigned-to property
mappedContact[key] = {
key: parseInt(value['assigned-to'].replace('user-', '')),
- label: value['display']
+ label: value['display'],
};
}
return;
@@ -108,7 +103,7 @@ export default function contactsReducer(state = initialState, action) {
// connection
return {
value: valueTwo.ID.toString(),
- name: entities.decode(valueTwo.post_title)
+ name: entities.decode(valueTwo.post_title),
};
}
if (
@@ -201,7 +196,7 @@ export default function contactsReducer(state = initialState, action) {
return;
}
case '[object Number]': {
- if(key === 'ID') {
+ if (key === 'ID') {
mappedContact[key] = value.toString();
} else {
mappedContact[key] = value;
@@ -233,7 +228,7 @@ export default function contactsReducer(state = initialState, action) {
// assigned-to property
mappedContact[key] = {
key: parseInt(value['assigned-to'].replace('user-', '')),
- label: value['display']
+ label: value['display'],
};
}
return;
@@ -247,7 +242,7 @@ export default function contactsReducer(state = initialState, action) {
// connection
return {
value: valueTwo.ID.toString(),
- name: entities.decode(valueTwo.post_title)
+ name: entities.decode(valueTwo.post_title),
};
}
if (
@@ -433,12 +428,14 @@ export default function contactsReducer(state = initialState, action) {
}
return {
...newState,
+ loading: false,
};
}
case actions.CONTACTS_SAVE_FAILURE:
return {
...newState,
error: action.error,
+ loading: false,
};
case actions.CONTACTS_GETBYID_START:
return {
@@ -452,9 +449,12 @@ export default function contactsReducer(state = initialState, action) {
const foundContact = newState.contacts.find(
(contactItem) => contactItem.ID.toString() === contact.ID,
);
- contact = {
- ...foundContact,
- };
+ // Fix to error when App try to get detail of non existing contact (browsing between several contacts) in OFFLINE mode
+ if (foundContact) {
+ contact = {
+ ...foundContact,
+ };
+ }
} else {
const mappedContact = {};
// MAP CONTACT TO CAN SAVE IT LATER
@@ -475,7 +475,7 @@ export default function contactsReducer(state = initialState, action) {
return;
}
case '[object Number]': {
- if(key === 'ID') {
+ if (key === 'ID') {
mappedContact[key] = value.toString();
} else {
mappedContact[key] = value;
@@ -507,7 +507,7 @@ export default function contactsReducer(state = initialState, action) {
// assigned-to property
mappedContact[key] = {
key: parseInt(value['assigned-to'].replace('user-', '')),
- label: value['display']
+ label: value['display'],
};
}
return;
@@ -521,7 +521,7 @@ export default function contactsReducer(state = initialState, action) {
// connection
return {
value: valueTwo.ID.toString(),
- name: entities.decode(valueTwo.post_title)
+ name: entities.decode(valueTwo.post_title),
};
}
if (
@@ -579,6 +579,9 @@ export default function contactsReducer(state = initialState, action) {
newState.contacts[contactIndex] = {
...contact,
};
+ } else {
+ // Add retrieved contact to contacts array (persist to OFFLINE mode)
+ newState.contacts.unshift(contact);
}
}
newState = {
@@ -600,47 +603,36 @@ export default function contactsReducer(state = initialState, action) {
loadingComments: true,
};
case actions.CONTACTS_GET_COMMENTS_SUCCESS: {
- const { comments, total, offline } = action;
- if (offline) {
- const date = new Date();
- const year = date.getUTCFullYear();
- let day = date.getUTCDate();
- let month = date.getUTCMonth() + 1;
- if (day < 10) day = `0${day}`;
- if (month < 10) month = `0${month}`;
- const curDay = `${year}-${month}-${day}`;
- let hours = date.getUTCHours();
- let minutes = date.getUTCMinutes();
- let seconds = date.getUTCSeconds();
- if (hours < 10) hours = `0${hours}`;
- if (minutes < 10) minutes = `0${minutes}`;
- if (seconds < 10) seconds = `0${seconds}`;
- const currentDate = `${curDay}T${hours}:${minutes}:${seconds}Z`;
- return {
- ...newState,
- comments: comments.map((comment) => ({
- ID: comment.ID,
- author: comment.author,
- date: currentDate,
- content: comment.comment,
- gravatar: 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g',
- contactId: comment.contactId,
- })),
- totalComments: total,
- loadingComments: false,
- };
+ const { comments, contactId, pagination } = action;
+
+ let mappedComments = comments.map((comment) => ({
+ ID: comment.comment_ID,
+ date: `${comment.comment_date_gmt.replace(' ', 'T')}Z`,
+ author: comment.comment_author,
+ // Decode HTML strings
+ content: entities.decode(comment.comment_content),
+ gravatar: comment.gravatar,
+ }));
+ // Check previous records existence; Only retrieve previous data if pagination its active (offset > 0)
+ let previousComments = [];
+ if (pagination.offset > 0 && newState.comments[contactId]) {
+ previousComments = newState.comments[contactId].data;
}
+
+ let newCommentState = {
+ ...newState.comments,
+ [contactId]: {
+ data: [...previousComments, ...mappedComments],
+ pagination: {
+ ...pagination,
+ offset: pagination.offset + pagination.limit, // UPDATE OFFSET
+ },
+ },
+ };
+
return {
...newState,
- comments: comments.map((comment) => ({
- ID: comment.comment_ID,
- date: `${comment.comment_date_gmt.replace(' ', 'T')}Z`,
- author: comment.comment_author,
- // Decode HTML strings
- content: entities.decode(comment.comment_content),
- gravatar: comment.gravatar,
- })),
- totalComments: total,
+ comments: newCommentState,
loadingComments: false,
};
}
@@ -656,49 +648,98 @@ export default function contactsReducer(state = initialState, action) {
loadingComments: true,
};
case actions.CONTACTS_SAVE_COMMENT_SUCCESS: {
- const { comment, offline } = action;
+ const { comment, contactId, offline } = action;
+ let newComment;
+
+ // Check previous records/pagination existence and return it
+ let previousComments = [],
+ pagination = {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ };
+ if (newState.comments[contactId]) {
+ previousComments = newState.comments[contactId].data;
+ pagination = newState.comments[contactId].pagination;
+ }
+ // Search existent comment with ID (update comment)
+ let foundCommentIndex = previousComments.findIndex(
+ (previousComment) => previousComment.ID === (comment.ID ? comment.ID : comment.comment_ID),
+ );
+
if (offline) {
- const date = new Date();
- const year = date.getUTCFullYear();
- let day = date.getUTCDate();
- let month = date.getUTCMonth() + 1;
- if (day < 10) day = `0${day}`;
- if (month < 10) month = `0${month}`;
- const curDay = `${year}-${month}-${day}`;
- let hours = date.getUTCHours();
- let minutes = date.getUTCMinutes();
- let seconds = date.getUTCSeconds();
- if (hours < 10) hours = `0${hours}`;
- if (minutes < 10) minutes = `0${minutes}`;
- if (seconds < 10) seconds = `0${seconds}`;
- const currentDate = `${curDay}T${hours}:${minutes}:${seconds}Z`;
- newState = {
- ...newState,
- newComment: {
+ if (foundCommentIndex > -1) {
+ newComment = {
+ ...comment,
+ };
+ } else {
+ const date = new Date();
+ const year = date.getUTCFullYear();
+ let day = date.getUTCDate();
+ let month = date.getUTCMonth() + 1;
+ if (day < 10) day = `0${day}`;
+ if (month < 10) month = `0${month}`;
+ const curDay = `${year}-${month}-${day}`;
+ let hours = date.getUTCHours();
+ let minutes = date.getUTCMinutes();
+ let seconds = date.getUTCSeconds();
+ if (hours < 10) hours = `0${hours}`;
+ if (minutes < 10) minutes = `0${minutes}`;
+ if (seconds < 10) seconds = `0${seconds}`;
+ const currentDate = `${curDay}T${hours}:${minutes}:${seconds}Z`;
+ newComment = {
ID: comment.ID,
author: comment.author,
date: currentDate,
content: comment.comment,
gravatar: 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g',
- contactID: comment.contactID,
- },
- loadingComments: false,
- };
+ };
+ }
} else {
- newState = {
- ...newState,
- newComment: {
+ if (foundCommentIndex > -1) {
+ newComment = {
+ ...comment,
+ };
+ } else {
+ newComment = {
ID: comment.comment_ID,
author: comment.comment_author,
date: `${comment.comment_date_gmt.replace(' ', 'T')}Z`,
// Decode HTML strings
content: entities.decode(comment.comment_content),
gravatar: 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g',
+ };
+ }
+ }
+
+ let newCommentState;
+ if (foundCommentIndex > -1) {
+ previousComments[foundCommentIndex] = newComment;
+
+ newCommentState = {
+ ...newState.comments,
+ [contactId]: {
+ data: [...previousComments],
+ pagination,
+ },
+ };
+ } else {
+ // Add new comment
+ newCommentState = {
+ ...newState.comments,
+ [contactId]: {
+ data: [...previousComments, newComment],
+ pagination,
},
- loadingComments: false,
};
}
- return newState;
+
+ return {
+ ...newState,
+ comments: newCommentState,
+ newComment: true,
+ loadingComments: false,
+ };
}
case actions.CONTACTS_SAVE_COMMENT_FAILURE:
return {
@@ -711,25 +752,45 @@ export default function contactsReducer(state = initialState, action) {
...newState,
loadingActivities: true,
};
- case actions.CONTACTS_GET_ACTIVITIES_SUCCESS:
+ case actions.CONTACTS_GET_ACTIVITIES_SUCCESS: {
+ const { activities, contactId, pagination } = action;
+
+ let mappedActivities = activities.map((activity) => ({
+ ID: activity.histid,
+ date: new Date(parseInt(activity.hist_time, 10) * 1000).toISOString(),
+ // Decode HTML strings
+ object_note: entities.decode(activity.object_note),
+ gravatar:
+ activity.gravatar === ''
+ ? 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g'
+ : activity.gravatar,
+ meta_id: activity.meta_id,
+ meta_key: activity.meta_key,
+ name: activity.name,
+ }));
+ // Check previous records existence; Only retrieve previous data if pagination its active (offset > 0)
+ let previousActivities = [];
+ if (pagination.offset > 0 && newState.activities[contactId]) {
+ previousActivities = newState.activities[contactId].data;
+ }
+
+ let newActivityState = {
+ ...newState.activities,
+ [contactId]: {
+ data: [...previousActivities, ...mappedActivities],
+ pagination: {
+ ...pagination,
+ offset: pagination.offset + pagination.limit, // UPDATE OFFSET
+ },
+ },
+ };
+
return {
...newState,
- activities: action.activities.map((activity) => ({
- ID: activity.histid,
- date: new Date(parseInt(activity.hist_time, 10) * 1000).toISOString(),
- // Decode HTML strings
- object_note: entities.decode(activity.object_note),
- gravatar:
- activity.gravatar === ''
- ? 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g'
- : activity.gravatar,
- meta_id: activity.meta_id,
- meta_key: activity.meta_key,
- name: activity.name,
- })),
- totalActivities: action.total,
+ activities: newActivityState,
loadingActivities: false,
};
+ }
case actions.CONTACTS_GET_ACTIVITIES_FAILURE:
return {
...newState,
@@ -802,6 +863,66 @@ export default function contactsReducer(state = initialState, action) {
settings: null,
contacts: [],
};
+ case actions.CONTACTS_DELETE_COMMENT_START:
+ return {
+ ...newState,
+ loadingComments: true,
+ };
+ case actions.CONTACTS_DELETE_COMMENT_SUCCESS: {
+ const { contactId, commentId } = action;
+
+ // Check previous records/pagination existence and return it
+ let previousComments = [],
+ pagination = {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ };
+ if (newState.comments[contactId]) {
+ previousComments = newState.comments[contactId].data;
+ pagination = newState.comments[contactId].pagination;
+ }
+ // Search existent comment with ID (update comment)
+ let foundCommentIndex = previousComments.findIndex(
+ (previousComment) => previousComment.ID === commentId,
+ );
+
+ // Delete comment
+ if (foundCommentIndex > -1) {
+ previousComments.splice(foundCommentIndex, 1);
+ }
+
+ let newCommentState = {
+ ...newState.comments,
+ [contactId]: {
+ data: [...previousComments],
+ pagination,
+ },
+ };
+ return {
+ ...newState,
+ comments: newCommentState,
+ loadingComments: false,
+ };
+ }
+ case actions.CONTACTS_DELETE_COMMENT_FAILURE:
+ return {
+ ...newState,
+ error: action.error,
+ loadingComments: false,
+ };
+ case actions.CONTACTS_LOADING_FALSE:
+ return {
+ ...newState,
+ loading: false,
+ };
+ case actions.CONTACTS_UPDATE_PREVIOUS: {
+ let { previousContacts } = action;
+ return {
+ ...newState,
+ previousContacts,
+ };
+ }
default:
return newState;
}
diff --git a/store/reducers/groups.reducer.js b/store/reducers/groups.reducer.js
index f5cbe43d..d36581b0 100644
--- a/store/reducers/groups.reducer.js
+++ b/store/reducers/groups.reducer.js
@@ -7,35 +7,30 @@ const initialState = {
error: null,
groups: [],
group: null,
- comments: null,
- newComment: null,
- activities: null,
- geonames: [],
- peopleGroups: null,
- totalComments: null,
- totalActivities: null,
+ comments: {},
+ newComment: false,
+ activities: {},
loadingComments: false,
loadingActivities: false,
saved: false,
settings: null,
offset: 0,
+ peopleGroups: null,
+ geonames: [],
foundGeonames: [],
geonamesLastModifiedDate: null,
geonamesLength: 0,
+ previousGroups: [],
};
export default function groupsReducer(state = initialState, action) {
let newState = {
...state,
group: null,
- peopleGroups: null,
- newComment: null,
+ newComment: false,
error: null,
- comments: null,
- totalComments: null,
- activities: null,
- totalActivities: null,
saved: false,
+ peopleGroups: null,
foundGeonames: null,
};
const entities = new Html5Entities();
@@ -144,7 +139,7 @@ export default function groupsReducer(state = initialState, action) {
// assigned-to property
mappedGroup[key] = {
key: parseInt(value['assigned-to'].replace('user-', '')),
- label: value['display']
+ label: value['display'],
};
}
return;
@@ -158,16 +153,18 @@ export default function groupsReducer(state = initialState, action) {
// connection
let object = {
value: valueTwo.ID.toString(),
- name: entities.decode(valueTwo.post_title)
+ name: entities.decode(valueTwo.post_title),
};
// groups
- if (Object.prototype.hasOwnProperty.call(valueTwo, 'baptized_member_count')) {
+ if (
+ Object.prototype.hasOwnProperty.call(valueTwo, 'baptized_member_count')
+ ) {
object = {
...object,
baptized_member_count: valueTwo.baptized_member_count,
};
}
- if(Object.prototype.hasOwnProperty.call(valueTwo, 'member_count')) {
+ if (Object.prototype.hasOwnProperty.call(valueTwo, 'member_count')) {
object = {
...object,
member_count: valueTwo.member_count,
@@ -305,7 +302,7 @@ export default function groupsReducer(state = initialState, action) {
// assigned-to property
mappedGroup[key] = {
key: parseInt(value['assigned-to'].replace('user-', '')),
- label: value['display']
+ label: value['display'],
};
}
return;
@@ -319,16 +316,18 @@ export default function groupsReducer(state = initialState, action) {
// connection
let object = {
value: valueTwo.ID.toString(),
- name: entities.decode(valueTwo.post_title)
+ name: entities.decode(valueTwo.post_title),
};
// groups
- if (Object.prototype.hasOwnProperty.call(valueTwo, 'baptized_member_count')) {
+ if (
+ Object.prototype.hasOwnProperty.call(valueTwo, 'baptized_member_count')
+ ) {
object = {
...object,
baptized_member_count: valueTwo.baptized_member_count,
};
}
- if(Object.prototype.hasOwnProperty.call(valueTwo, 'member_count')) {
+ if (Object.prototype.hasOwnProperty.call(valueTwo, 'member_count')) {
object = {
...object,
member_count: valueTwo.member_count,
@@ -537,12 +536,14 @@ export default function groupsReducer(state = initialState, action) {
}
return {
...newState,
+ loading: false,
};
}
case actions.GROUPS_SAVE_FAILURE:
return {
...newState,
error: action.error,
+ loading: false,
};
case actions.GROUPS_GETBYID_START:
return {
@@ -556,9 +557,12 @@ export default function groupsReducer(state = initialState, action) {
const foundGroup = newState.groups.find(
(groupItem) => groupItem.ID.toString() === group.ID,
);
- group = {
- ...foundGroup,
- };
+ // Fix to error when App try to get detail of non existing group (browsing between several groups) in OFFLINE mode
+ if (foundGroup) {
+ group = {
+ ...foundGroup,
+ };
+ }
} else {
const mappedGroup = {};
// MAP GROUP TO CAN SAVE IT LATER
@@ -613,7 +617,7 @@ export default function groupsReducer(state = initialState, action) {
// assigned-to property
mappedGroup[key] = {
key: parseInt(value['assigned-to'].replace('user-', '')),
- label: value['display']
+ label: value['display'],
};
}
return;
@@ -627,16 +631,18 @@ export default function groupsReducer(state = initialState, action) {
// connection
let object = {
value: valueTwo.ID.toString(),
- name: entities.decode(valueTwo.post_title)
+ name: entities.decode(valueTwo.post_title),
};
// groups
- if (Object.prototype.hasOwnProperty.call(valueTwo, 'baptized_member_count')) {
+ if (
+ Object.prototype.hasOwnProperty.call(valueTwo, 'baptized_member_count')
+ ) {
object = {
...object,
baptized_member_count: valueTwo.baptized_member_count,
};
}
- if(Object.prototype.hasOwnProperty.call(valueTwo, 'member_count')) {
+ if (Object.prototype.hasOwnProperty.call(valueTwo, 'member_count')) {
object = {
...object,
member_count: valueTwo.member_count,
@@ -705,6 +711,9 @@ export default function groupsReducer(state = initialState, action) {
newState.groups[groupIndex] = {
...group,
};
+ } else {
+ // Add retrieved group to groups array (persist to OFFLINE mode)
+ newState.groups.unshift(group);
}
}
newState = {
@@ -726,47 +735,36 @@ export default function groupsReducer(state = initialState, action) {
loadingComments: true,
};
case actions.GROUPS_GET_COMMENTS_SUCCESS: {
- const { comments, total, offline } = action;
- if (offline) {
- const date = new Date();
- const year = date.getUTCFullYear();
- let day = date.getUTCDate();
- let month = date.getUTCMonth() + 1;
- if (day < 10) day = `0${day}`;
- if (month < 10) month = `0${month}`;
- const curDay = `${year}-${month}-${day}`;
- let hours = date.getUTCHours();
- let minutes = date.getUTCMinutes();
- let seconds = date.getUTCSeconds();
- if (hours < 10) hours = `0${hours}`;
- if (minutes < 10) minutes = `0${minutes}`;
- if (seconds < 10) seconds = `0${seconds}`;
- const currentDate = `${curDay}T${hours}:${minutes}:${seconds}Z`;
- return {
- ...newState,
- comments: comments.map((comment) => ({
- ID: comment.ID,
- author: comment.author,
- date: currentDate,
- content: comment.comment,
- gravatar: 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g',
- contactId: comment.contactId,
- })),
- totalComments: total,
- loadingComments: false,
- };
+ const { comments, groupId, pagination } = action;
+
+ let mappedComments = comments.map((comment) => ({
+ ID: comment.comment_ID,
+ date: `${comment.comment_date_gmt.replace(' ', 'T')}Z`,
+ author: comment.comment_author,
+ // Decode HTML strings
+ content: entities.decode(comment.comment_content),
+ gravatar: comment.gravatar,
+ }));
+ // Check previous records existence; Only retrieve previous data if pagination its active (offset > 0)
+ let previousComments = [];
+ if (pagination.offset > 0 && newState.comments[groupId]) {
+ previousComments = newState.comments[groupId].data;
}
+
+ let newCommentState = {
+ ...newState.comments,
+ [groupId]: {
+ data: [...previousComments, ...mappedComments],
+ pagination: {
+ ...pagination,
+ offset: pagination.offset + pagination.limit, // UPDATE OFFSET
+ },
+ },
+ };
+
return {
...newState,
- comments: comments.map((comment) => ({
- ID: comment.comment_ID,
- date: `${comment.comment_date_gmt.replace(' ', 'T')}Z`,
- author: comment.comment_author,
- // Decode HTML strings
- content: entities.decode(comment.comment_content),
- gravatar: comment.gravatar,
- })),
- totalComments: total,
+ comments: newCommentState,
loadingComments: false,
};
}
@@ -782,49 +780,98 @@ export default function groupsReducer(state = initialState, action) {
loadingComments: true,
};
case actions.GROUPS_SAVE_COMMENT_SUCCESS: {
- const { comment, offline } = action;
+ const { comment, groupId, offline } = action;
+ let newComment;
+
+ // Check previous records/pagination existence and return it
+ let previousComments = [],
+ pagination = {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ };
+ if (newState.comments[groupId]) {
+ previousComments = newState.comments[groupId].data;
+ pagination = newState.comments[groupId].pagination;
+ }
+ // Search existent comment with ID (update comment)
+ let foundCommentIndex = previousComments.findIndex(
+ (previousComment) => previousComment.ID === (comment.ID ? comment.ID : comment.comment_ID),
+ );
+
if (offline) {
- const date = new Date();
- const year = date.getUTCFullYear();
- let day = date.getUTCDate();
- let month = date.getUTCMonth() + 1;
- if (day < 10) day = `0${day}`;
- if (month < 10) month = `0${month}`;
- const curDay = `${year}-${month}-${day}`;
- let hours = date.getUTCHours();
- let minutes = date.getUTCMinutes();
- let seconds = date.getUTCSeconds();
- if (hours < 10) hours = `0${hours}`;
- if (minutes < 10) minutes = `0${minutes}`;
- if (seconds < 10) seconds = `0${seconds}`;
- const currentDate = `${curDay}T${hours}:${minutes}:${seconds}Z`;
- newState = {
- ...newState,
- newComment: {
+ if (foundCommentIndex > -1) {
+ newComment = {
+ ...comment,
+ };
+ } else {
+ const date = new Date();
+ const year = date.getUTCFullYear();
+ let day = date.getUTCDate();
+ let month = date.getUTCMonth() + 1;
+ if (day < 10) day = `0${day}`;
+ if (month < 10) month = `0${month}`;
+ const curDay = `${year}-${month}-${day}`;
+ let hours = date.getUTCHours();
+ let minutes = date.getUTCMinutes();
+ let seconds = date.getUTCSeconds();
+ if (hours < 10) hours = `0${hours}`;
+ if (minutes < 10) minutes = `0${minutes}`;
+ if (seconds < 10) seconds = `0${seconds}`;
+ const currentDate = `${curDay}T${hours}:${minutes}:${seconds}Z`;
+ newComment = {
ID: comment.ID,
author: comment.author,
date: currentDate,
content: comment.comment,
gravatar: 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g',
- contactID: comment.contactID,
- },
- loadingComments: false,
- };
+ };
+ }
} else {
- newState = {
- ...newState,
- newComment: {
+ if (foundCommentIndex > -1) {
+ newComment = {
+ ...comment,
+ };
+ } else {
+ newComment = {
ID: comment.comment_ID,
author: comment.comment_author,
date: `${comment.comment_date_gmt.replace(' ', 'T')}Z`,
// Decode HTML strings
content: entities.decode(comment.comment_content),
gravatar: 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g',
+ };
+ }
+ }
+
+ let newCommentState;
+ if (foundCommentIndex > -1) {
+ previousComments[foundCommentIndex] = newComment;
+
+ newCommentState = {
+ ...newState.comments,
+ [groupId]: {
+ data: [...previousComments],
+ pagination,
+ },
+ };
+ } else {
+ // Add new comment
+ newCommentState = {
+ ...newState.comments,
+ [groupId]: {
+ data: [...previousComments, newComment],
+ pagination,
},
- loadingComments: false,
};
}
- return newState;
+
+ return {
+ ...newState,
+ comments: newCommentState,
+ newComment: true,
+ loadingComments: false,
+ };
}
case actions.GROUPS_SAVE_COMMENT_FAILURE:
return {
@@ -837,25 +884,45 @@ export default function groupsReducer(state = initialState, action) {
...newState,
loadingActivities: true,
};
- case actions.GROUPS_GET_ACTIVITIES_SUCCESS:
- return {
- ...newState,
- activities: action.activities.map((activity) => ({
- ID: activity.histid,
- date: new Date(parseInt(activity.hist_time, 10) * 1000).toISOString(),
- // Decode HTML strings
- object_note: entities.decode(activity.object_note),
- gravatar:
- activity.gravatar === ''
- ? 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g'
- : activity.gravatar,
- meta_id: activity.meta_id,
- meta_key: activity.meta_key,
- name: activity.name,
- })),
- totalActivities: action.total,
+ case actions.GROUPS_GET_ACTIVITIES_SUCCESS: {
+ const { activities, groupId, pagination } = action;
+
+ let mappedActivities = activities.map((activity) => ({
+ ID: activity.histid,
+ date: new Date(parseInt(activity.hist_time, 10) * 1000).toISOString(),
+ // Decode HTML strings
+ object_note: entities.decode(activity.object_note),
+ gravatar:
+ activity.gravatar === ''
+ ? 'https://secure.gravatar.com/avatar/?s=16&d=mm&r=g'
+ : activity.gravatar,
+ meta_id: activity.meta_id,
+ meta_key: activity.meta_key,
+ name: activity.name,
+ }));
+ // Check previous records existence; Only retrieve previous data if pagination its active (offset > 0)
+ let previousActivities = [];
+ if (pagination.offset > 0 && newState.activities[groupId]) {
+ previousActivities = newState.activities[groupId].data;
+ }
+
+ let newActivityState = {
+ ...newState.activities,
+ [groupId]: {
+ data: [...previousActivities, ...mappedActivities],
+ pagination: {
+ ...pagination,
+ offset: pagination.offset + pagination.limit, // UPDATE OFFSET
+ },
+ },
+ };
+
+ return {
+ ...newState,
+ activities: newActivityState,
loadingActivities: false,
};
+ }
case actions.GROUPS_GET_ACTIVITIES_FAILURE:
return {
...newState,
@@ -978,6 +1045,66 @@ export default function groupsReducer(state = initialState, action) {
error: action.error,
};
}
+ case actions.GROUPS_DELETE_COMMENT_START:
+ return {
+ ...newState,
+ loadingComments: true,
+ };
+ case actions.GROUPS_DELETE_COMMENT_SUCCESS: {
+ const { groupId, commentId } = action;
+
+ // Check previous records/pagination existence and return it
+ let previousComments = [],
+ pagination = {
+ limit: 10,
+ offset: 0,
+ total: 0,
+ };
+ if (newState.comments[groupId]) {
+ previousComments = newState.comments[groupId].data;
+ pagination = newState.comments[groupId].pagination;
+ }
+ // Search existent comment with ID (update comment)
+ let foundCommentIndex = previousComments.findIndex(
+ (previousComment) => previousComment.ID === commentId,
+ );
+
+ // Delete comment
+ if (foundCommentIndex > -1) {
+ previousComments.splice(foundCommentIndex, 1);
+ }
+
+ let newCommentState = {
+ ...newState.comments,
+ [groupId]: {
+ data: [...previousComments],
+ pagination,
+ },
+ };
+ return {
+ ...newState,
+ comments: newCommentState,
+ loadingComments: false,
+ };
+ }
+ case actions.GROUPS_DELETE_COMMENT_FAILURE:
+ return {
+ ...newState,
+ error: action.error,
+ loadingComments: false,
+ };
+ case actions.GROUPS_LOADING_FALSE:
+ return {
+ ...newState,
+ loading: false,
+ };
+ case actions.GROUPS_UPDATE_PREVIOUS: {
+ let { previousGroups } = action;
+ return {
+ ...newState,
+ previousGroups,
+ };
+ }
default:
return newState;
}
diff --git a/store/reducers/questionnaire.reducer.js b/store/reducers/questionnaire.reducer.js
index 36c0cbbe..d1931852 100644
--- a/store/reducers/questionnaire.reducer.js
+++ b/store/reducers/questionnaire.reducer.js
@@ -3,257 +3,12 @@ import produce, { setAutoFreeze } from 'immer';
setAutoFreeze(false);
import set from 'lodash/set';
-/*
const initialState = {
loading: false,
error: null,
- questionnaire: {
- forms: [
- ]
- }
-}
-*/
-
-const initialState = {
- loading: false,
- error: null,
- questionnaire: {
- forms: [
- {
- seq: '2',
- title: 'What THEY Did',
- questions: [
- {
- seq: '2.1',
- title: "Did they do last meeting's commitment?",
- required: true,
- type: 'radio',
- options: [
- {
- seq: '2.1.1',
- title: 'Yes',
- selected: false,
- },
- {
- seq: '2.1.2',
- title: 'No',
- selected: false,
- },
- {
- seq: '2.1.3',
- title: 'N/A',
- selected: false,
- },
- ],
- },
- {
- seq: '2.2',
- title: 'Other Activities',
- required: false,
- type: 'checkbox',
- options: [
- {
- seq: '2.2.1',
- title: 'Shared with someone recently',
- selected: false,
- },
- {
- seq: '2.2.2',
- title: 'In the Word since last meeting',
- selected: false,
- },
- ],
- },
- ],
- },
- {
- seq: '3',
- title: 'What I Did',
- questions: [
- {
- seq: '3.1',
- title: 'Held to the Study Plan?',
- required: true,
- type: 'radio',
- options: [
- {
- seq: '3.1.1',
- title: 'Yes',
- selected: false,
- },
- {
- seq: '3.1.2',
- title: 'No (Study was for where they were at)',
- selected: false,
- },
- ],
- },
- {
- seq: '3.2',
- title: 'Other Activities',
- required: false,
- type: 'checkbox',
- options: [
- {
- seq: '3.2.1',
- title: 'Prayed before the meeting',
- selected: false,
- },
- {
- seq: '3.2.2',
- title: 'Encouraged them',
- selected: false,
- },
- {
- seq: '3.2.3',
- title: 'Cast vision to share with their groups',
- selected: false,
- },
- {
- seq: '3.2.4',
- title: '30+ min caring/loving them',
- selected: false,
- },
- {
- seq: '3.2.5',
- title: '90% or more in local language',
- selected: false,
- },
- {
- seq: '3.2.6',
- title: 'Listened more than I talked',
- selected: false,
- },
- ],
- },
- ],
- },
- {
- seq: '1',
- title: 'What WE Did',
- questions: [
- {
- seq: '1.1',
- title: 'Type of Meeting',
- required: true,
- type: 'radio',
- options: [
- {
- seq: '1.1.1',
- title: 'Relational hangout',
- selected: false,
- },
- {
- seq: '1.1.2',
- title: 'Spiritual discussion',
- selected: false,
- },
- {
- seq: '1.1.3',
- title: 'Bible Study',
- selected: false,
- questions: [
- {
- seq: '1.1.3.1',
- title: 'What Scripture?',
- required: true,
- type: 'input',
- value: '',
- },
- {
- seq: '1.1.3.2',
- title: 'Type of Study',
- required: false,
- type: 'radio',
- options: [
- {
- seq: '1.1.3.2.1',
- title: 'Discovery Bible Study',
- selected: false,
- },
- {
- seq: '1.1.3.2.2',
- title: '4 Fields',
- selected: false,
- questions: [
- {
- seq: '1.1.3.2.2.1',
- title: 'Yet another nested question',
- required: false,
- type: 'checkbox',
- options: [
- {
- seq: '1.1.3.2.2.1.1',
- title: 'Y1',
- selected: false,
- },
- {
- seq: '1.1.3.2.2.1.2',
- title: 'Y2',
- selected: false,
- },
- {
- seq: '1.1.3.2.2.1.3',
- title: 'Y3',
- selected: false,
- },
- ],
- },
- ],
- },
- {
- seq: '1.1.3.2.3',
- title: 'Inductive Bible Study',
- selected: false,
- },
- {
- seq: '1.1.3.2.4',
- title: '9 Studies for Seekers',
- selected: false,
- },
- {
- seq: '1.1.3.2.5',
- title: 'Teaching',
- selected: false,
- },
- {
- seq: '1.1.3.2.6',
- title: 'Other',
- selected: false,
- },
- ],
- },
- ],
- },
- ],
- },
- {
- seq: '1.2',
- title: 'Other Activities',
- required: false,
- type: 'checkbox',
- options: [
- {
- seq: '1.2.1',
- title: 'Worshiped',
- selected: false,
- },
- {
- seq: '1.2.2',
- title: 'Prayed',
- selected: false,
- },
- {
- seq: '1.2.3',
- title: 'Confessed our sins',
- selected: false,
- },
- ],
- },
- ],
- },
- ],
- },
+ save: null,
+ questionnaires: [],
+ questionnaire: null,
};
/*
@@ -276,8 +31,41 @@ function recursivelyBuildObjectString(objStr, seqArray, idx) {
export default function questionnaireReducer(state = initialState, action) {
return produce(state, (draft) => {
switch (action.type) {
+ case actions.GET_QUESTIONNAIRES_ACTIVE:
+ return draft;
+ case actions.GET_QUESTIONNAIRES_ACTIVE_START:
+ return draft;
+ case actions.GET_QUESTIONNAIRES_ACTIVE_SUCCESS:
+ draft.questionnaires = action.payload.questionnaires;
+ return draft;
+ case actions.GET_QUESTIONNAIRES_ACTIVE_RESPONSE:
+ return draft;
+ case actions.GET_QUESTIONNAIRES_ACTIVE_FAILURE:
+ return draft;
+ case actions.GET_QUESTIONNAIRE_BY_ID:
+ draft.loading = true;
+ return draft;
+ case actions.GET_QUESTIONNAIRE_BY_ID_START:
+ return draft;
+ case actions.GET_QUESTIONNAIRE_BY_ID_RESPONSE:
+ return draft;
+ case actions.GET_QUESTIONNAIRE_BY_ID_SUCCESS:
+ draft.loading = false;
+ draft.save = null;
+ draft.error = null;
+ draft.questionnaire = action.payload.questionnaire;
+ return draft;
+ case actions.GET_QUESTIONNAIRE_BY_ID_FAILURE:
+ draft.loading = false;
+ draft.save = null;
+ draft.error = action.error;
+ return draft;
case actions.RESET_STATE:
- draft = initialState;
+ if (draft.save != null) {
+ draft.questionnaire = null;
+ draft.save = null;
+ }
+ draft.error = null;
return draft;
case actions.SET_QUESTION:
const seqArray = action.question.seq.split('.');
@@ -298,12 +86,20 @@ export default function questionnaireReducer(state = initialState, action) {
}
return draft;
case actions.SUBMIT_QUESTIONNAIRE:
- console.log(
- JSON.stringify({
- questionnaire: action.questionnaire,
- }),
- );
- draft = initialState;
+ return draft;
+ case actions.SUBMIT_QUESTIONNAIRE_START:
+ return draft;
+ case actions.SUBMIT_QUESTIONNAIRE_RESPONSE:
+ return draft;
+ case actions.SUBMIT_QUESTIONNAIRE_SUCCESS:
+ draft.loading = false;
+ draft.save = true;
+ draft.error = null;
+ return draft;
+ case actions.SUBMIT_QUESTIONNAIRE_FAILURE:
+ draft.loading = false;
+ draft.save = null;
+ draft.error = action.error;
return draft;
default:
return draft;
diff --git a/store/reducers/request.reducer.js b/store/reducers/request.reducer.js
index 0493c9fd..7c2b78ee 100644
--- a/store/reducers/request.reducer.js
+++ b/store/reducers/request.reducer.js
@@ -369,6 +369,28 @@ export default function requestReducer(state = initialState, action) {
} else if (actionToModify.data.method === 'GET') {
// filter out redundant GET requests
queue = queue.filter((existing) => existing.url !== actionToModify.url);
+ } else if (actionToModify.data.method === 'DELETE') {
+ if (!actionToModify.isConnected) {
+ // OFFLINE DELETE (i.e: comments)
+ let id = actionToModify.url.split('/');
+ id = id[id.length - 1];
+ let urlWithoutId = actionToModify.url.replace(id, '');
+ // Delete previous CREATE/EDIT request to the comment
+ queue = queue.filter((existing) => existing.url !== urlWithoutId);
+
+ // Add delete request ONLY if its ONLINE comment (not LOCAL)
+ if (isNaN(id)) {
+ queue = [...queue];
+ } else {
+ queue = [...queue, actionToModify];
+ }
+
+ return {
+ ...newState,
+ queue: queue,
+ currentAction: actionToModify,
+ };
+ }
}
newState = {
...newState,
@@ -407,7 +429,6 @@ export default function requestReducer(state = initialState, action) {
queue: [],
currentAction: {},
};
- return newState;
default:
return newState;
}
diff --git a/store/sagas.js b/store/sagas.js
index 971cd75b..aad41d67 100644
--- a/store/sagas.js
+++ b/store/sagas.js
@@ -7,6 +7,7 @@ import contactsSaga from './sagas/contacts.sagas';
import groupsSaga from './sagas/groups.sagas';
import usersSaga from './sagas/users.sagas';
import notificationsSaga from './sagas/notifications.sagas';
+import questionnaireSaga from './sagas/questionnaire.sagas';
// single entry point to start all Sagas at once
export default function* rootSaga() {
@@ -18,5 +19,6 @@ export default function* rootSaga() {
groupsSaga(),
usersSaga(),
notificationsSaga(),
+ questionnaireSaga(),
]);
}
diff --git a/store/sagas/contacts.sagas.js b/store/sagas/contacts.sagas.js
index 12523205..a6c13a9b 100644
--- a/store/sagas/contacts.sagas.js
+++ b/store/sagas/contacts.sagas.js
@@ -136,10 +136,9 @@ export function* save({ domain, token, contactData }) {
...jsonData,
assigned_to: {
key: assignedToId,
- label: usersList.find((user) => user.key === assignedToId).label
- }
+ label: usersList.find((user) => user.key === assignedToId).label,
+ },
};
-
}
yield put({
type: actions.CONTACTS_SAVE_SUCCESS,
@@ -211,14 +210,20 @@ export function* saveComment({ domain, token, contactId, commentData }) {
yield put({
type: 'REQUEST',
payload: {
- url: `https://${domain}/wp-json/dt-posts/v2/contacts/${contactId}/comments`,
+ url: `https://${domain}/wp-json/dt-posts/v2/contacts/${contactId}/comments/${
+ commentData.ID ? commentData.ID : ''
+ }`,
data: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
- body: JSON.stringify(commentData),
+ body: JSON.stringify({
+ comment: commentData.ID ? commentData.content : commentData.comment,
+ comment_type: 'comment',
+ ID: commentData.ID ? commentData.ID : undefined,
+ }),
},
isConnected,
action: actions.CONTACTS_SAVE_COMMENT_RESPONSE,
@@ -233,7 +238,8 @@ export function* saveComment({ domain, token, contactId, commentData }) {
if (response.status === 200) {
yield put({
type: actions.CONTACTS_SAVE_COMMENT_SUCCESS,
- comment: jsonData,
+ comment: commentData.ID ? commentData : jsonData,
+ contactId,
});
} else {
yield put({
@@ -249,11 +255,11 @@ export function* saveComment({ domain, token, contactId, commentData }) {
jsonData = {
...response,
author: authorName,
- contactId,
};
yield put({
type: actions.CONTACTS_SAVE_COMMENT_SUCCESS,
- comment: jsonData,
+ comment: commentData.ID ? commentData : jsonData,
+ contactId,
offline: true,
});
}
@@ -268,65 +274,45 @@ export function* saveComment({ domain, token, contactId, commentData }) {
}
}
-export function* getCommentsByContact({ domain, token, contactId, offset, limit }) {
+export function* getCommentsByContact({ domain, token, contactId, pagination }) {
const isConnected = yield select((state) => state.networkConnectivityReducer.isConnected);
yield put({ type: actions.CONTACTS_GET_COMMENTS_START });
try {
- if (!isConnected || isNaN(contactId)) {
- let queue = yield select((state) => state.requestReducer.queue);
- const authorName = yield select((state) => state.userReducer.userData.username);
- queue = queue.filter(
- (requestQueue) =>
- requestQueue.data.method === 'POST' &&
- requestQueue.action === 'CONTACTS_SAVE_COMMENT_RESPONSE' &&
- requestQueue.url.includes(`contacts/${contactId}/comments`),
- );
+ yield put({
+ type: 'REQUEST',
+ payload: {
+ url: `https://${domain}/wp-json/dt-posts/v2/contacts/${contactId}/comments?number=${pagination.limit}&offset=${pagination.offset}`,
+ data: {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ },
+ action: actions.CONTACTS_GET_COMMENTS_RESPONSE,
+ },
+ });
+ let response = yield take(actions.CONTACTS_GET_COMMENTS_RESPONSE);
+ response = response.payload;
+ const jsonData = response.data;
+ if (response.status === 200) {
yield put({
type: actions.CONTACTS_GET_COMMENTS_SUCCESS,
- comments: queue.map((request) => {
- const requestBody = JSON.parse(request.data.body);
- return {
- ...requestBody,
- author: authorName,
- contactId,
- };
- }),
- total: queue.length,
- offline: true,
+ comments: jsonData.comments,
+ contactId: contactId,
+ pagination: {
+ ...pagination,
+ total: jsonData.total,
+ },
});
} else {
yield put({
- type: 'REQUEST',
- payload: {
- url: `https://${domain}/wp-json/dt-posts/v2/contacts/${contactId}/comments?number=${limit}&offset=${offset}`,
- data: {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`,
- },
- },
- action: actions.CONTACTS_GET_COMMENTS_RESPONSE,
+ type: actions.CONTACTS_GET_COMMENTS_FAILURE,
+ error: {
+ code: jsonData.code,
+ message: jsonData.message,
},
});
- let response = yield take(actions.CONTACTS_GET_COMMENTS_RESPONSE);
- response = response.payload;
- const jsonData = response.data;
- if (response.status === 200) {
- yield put({
- type: actions.CONTACTS_GET_COMMENTS_SUCCESS,
- comments: jsonData.comments,
- total: jsonData.total,
- });
- } else {
- yield put({
- type: actions.CONTACTS_GET_COMMENTS_FAILURE,
- error: {
- code: jsonData.code,
- message: jsonData.message,
- },
- });
- }
}
} catch (error) {
yield put({
@@ -339,7 +325,7 @@ export function* getCommentsByContact({ domain, token, contactId, offset, limit
}
}
-export function* getActivitiesByContact({ domain, token, contactId, offset, limit }) {
+export function* getActivitiesByContact({ domain, token, contactId, pagination }) {
yield put({ type: actions.CONTACTS_GET_ACTIVITIES_START });
if (isNaN(contactId)) {
yield put({
@@ -351,7 +337,7 @@ export function* getActivitiesByContact({ domain, token, contactId, offset, limi
yield put({
type: 'REQUEST',
payload: {
- url: `https://${domain}/wp-json/dt-posts/v2/contacts/${contactId}/activity?number=${limit}&offset=${offset}`,
+ url: `https://${domain}/wp-json/dt-posts/v2/contacts/${contactId}/activity?number=${pagination.limit}&offset=${pagination.offset}`,
data: {
method: 'GET',
headers: {
@@ -370,7 +356,11 @@ export function* getActivitiesByContact({ domain, token, contactId, offset, limi
yield put({
type: actions.CONTACTS_GET_ACTIVITIES_SUCCESS,
activities: jsonData.activity,
- total: jsonData.total,
+ contactId: contactId,
+ pagination: {
+ ...pagination,
+ total: jsonData.total,
+ },
});
} else {
yield put({
@@ -440,6 +430,65 @@ export function* getSettings({ domain, token }) {
}
}
+export function* deleteComment({ domain, token, contactId, commentId }) {
+ const isConnected = yield select((state) => state.networkConnectivityReducer.isConnected);
+
+ yield put({ type: actions.CONTACTS_DELETE_COMMENT_START });
+
+ yield put({
+ type: 'REQUEST',
+ payload: {
+ url: `https://${domain}/wp-json/dt-posts/v2/contacts/${contactId}/comments/${commentId}`,
+ data: {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ },
+ isConnected,
+ action: actions.CONTACTS_DELETE_COMMENT_RESPONSE,
+ },
+ });
+
+ try {
+ let response = yield take(actions.CONTACTS_DELETE_COMMENT_RESPONSE);
+ response = response.payload;
+ let jsonData = response.data;
+ if (isConnected) {
+ if (response.status === 200) {
+ yield put({
+ type: actions.CONTACTS_DELETE_COMMENT_SUCCESS,
+ contactId,
+ commentId,
+ });
+ } else {
+ yield put({
+ type: actions.CONTACTS_DELETE_COMMENT_FAILURE,
+ error: {
+ code: jsonData.code,
+ message: jsonData.message,
+ },
+ });
+ }
+ } else {
+ yield put({
+ type: actions.CONTACTS_DELETE_COMMENT_SUCCESS,
+ contactId,
+ commentId,
+ });
+ }
+ } catch (error) {
+ yield put({
+ type: actions.CONTACTS_DELETE_COMMENT_FAILURE,
+ error: {
+ code: '400',
+ message: 'Unable to process the request. Please try again later.',
+ },
+ });
+ }
+}
+
export default function* contactsSaga() {
yield all([
takeLatest(actions.CONTACTS_GETALL, getAll),
@@ -449,5 +498,6 @@ export default function* contactsSaga() {
takeEvery(actions.CONTACTS_SAVE_COMMENT, saveComment),
takeEvery(actions.CONTACTS_GET_ACTIVITIES, getActivitiesByContact),
takeEvery(actions.CONTACTS_GET_SETTINGS, getSettings),
+ takeEvery(actions.CONTACTS_DELETE_COMMENT, deleteComment),
]);
}
diff --git a/store/sagas/groups.sagas.js b/store/sagas/groups.sagas.js
index 2d79028d..c6c1a78d 100644
--- a/store/sagas/groups.sagas.js
+++ b/store/sagas/groups.sagas.js
@@ -122,10 +122,9 @@ export function* saveGroup({ domain, token, groupData }) {
...jsonData,
assigned_to: {
key: assignedToId,
- label: usersList.find((user) => user.key === assignedToId).label
- }
+ label: usersList.find((user) => user.key === assignedToId).label,
+ },
};
-
}
yield put({
type: actions.GROUPS_SAVE_SUCCESS,
@@ -191,66 +190,45 @@ export function* getById({ domain, token, groupId }) {
}
}
-export function* getCommentsByGroup({ domain, token, groupId, offset, limit }) {
+export function* getCommentsByGroup({ domain, token, groupId, pagination }) {
const isConnected = yield select((state) => state.networkConnectivityReducer.isConnected);
yield put({ type: actions.GROUPS_GET_COMMENTS_START });
-
try {
- if (!isConnected || isNaN(groupId)) {
- let queue = yield select((state) => state.requestReducer.queue);
- const authorName = yield select((state) => state.userReducer.userData.username);
- queue = queue.filter(
- (requestQueue) =>
- requestQueue.data.method === 'POST' &&
- requestQueue.action === 'GROUPS_SAVE_COMMENT_RESPONSE' &&
- requestQueue.url.includes(`groups/${groupId}/comments`),
- );
+ yield put({
+ type: 'REQUEST',
+ payload: {
+ url: `https://${domain}/wp-json/dt-posts/v2/groups/${groupId}/comments?number=${pagination.limit}&offset=${pagination.offset}`,
+ data: {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ },
+ action: actions.GROUPS_GET_COMMENTS_RESPONSE,
+ },
+ });
+ let response = yield take(actions.GROUPS_GET_COMMENTS_RESPONSE);
+ response = response.payload;
+ const jsonData = response.data;
+ if (response.status === 200) {
yield put({
type: actions.GROUPS_GET_COMMENTS_SUCCESS,
- comments: queue.map((request) => {
- const requestBody = JSON.parse(request.data.body);
- return {
- ...requestBody,
- author: authorName,
- groupId,
- };
- }),
- total: queue.length,
- offline: true,
+ comments: jsonData.comments,
+ groupId: groupId,
+ pagination: {
+ ...pagination,
+ total: jsonData.total,
+ },
});
} else {
yield put({
- type: 'REQUEST',
- payload: {
- url: `https://${domain}/wp-json/dt-posts/v2/groups/${groupId}/comments?number=${limit}&offset=${offset}`,
- data: {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`,
- },
- },
- action: actions.GROUPS_GET_COMMENTS_RESPONSE,
+ type: actions.GROUPS_GET_COMMENTS_FAILURE,
+ error: {
+ code: jsonData.code,
+ message: jsonData.message,
},
});
- let response = yield take(actions.GROUPS_GET_COMMENTS_RESPONSE);
- response = response.payload;
- const jsonData = response.data;
- if (response.status === 200) {
- yield put({
- type: actions.GROUPS_GET_COMMENTS_SUCCESS,
- comments: jsonData.comments,
- total: jsonData.total,
- });
- } else {
- yield put({
- type: actions.GROUPS_GET_COMMENTS_FAILURE,
- error: {
- code: jsonData.code,
- message: jsonData.message,
- },
- });
- }
}
} catch (error) {
yield put({
@@ -271,14 +249,20 @@ export function* saveComment({ domain, token, groupId, commentData }) {
yield put({
type: 'REQUEST',
payload: {
- url: `https://${domain}/wp-json/dt-posts/v2/groups/${groupId}/comments`,
+ url: `https://${domain}/wp-json/dt-posts/v2/groups/${groupId}/comments/${
+ commentData.ID ? commentData.ID : ''
+ }`,
data: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
- body: JSON.stringify(commentData),
+ body: JSON.stringify({
+ comment: commentData.ID ? commentData.content : commentData.comment,
+ comment_type: 'comment',
+ ID: commentData.ID ? commentData.ID : undefined,
+ }),
},
isConnected,
action: actions.GROUPS_SAVE_COMMENT_RESPONSE,
@@ -293,7 +277,8 @@ export function* saveComment({ domain, token, groupId, commentData }) {
if (response.status === 200) {
yield put({
type: actions.GROUPS_SAVE_COMMENT_SUCCESS,
- comment: jsonData,
+ comment: commentData.ID ? commentData : jsonData,
+ groupId,
});
} else {
yield put({
@@ -309,11 +294,11 @@ export function* saveComment({ domain, token, groupId, commentData }) {
jsonData = {
...response,
author: authorName,
- groupId,
};
yield put({
type: actions.GROUPS_SAVE_COMMENT_SUCCESS,
- comment: jsonData,
+ comment: commentData.ID ? commentData : jsonData,
+ groupId,
offline: true,
});
}
@@ -422,13 +407,13 @@ export function* getPeopleGroups({ domain, token }) {
}
}
-export function* getActivitiesByGroup({ domain, token, groupId, offset, limit }) {
+export function* getActivitiesByGroup({ domain, token, groupId, pagination }) {
yield put({ type: actions.GROUPS_GET_ACTIVITIES_START });
yield put({
type: 'REQUEST',
payload: {
- url: `https://${domain}/wp-json/dt-posts/v2/groups/${groupId}/activity?number=${limit}&offset=${offset}`,
+ url: `https://${domain}/wp-json/dt-posts/v2/groups/${groupId}/activity?number=${pagination.limit}&offset=${pagination.offset}`,
data: {
method: 'GET',
headers: {
@@ -448,7 +433,11 @@ export function* getActivitiesByGroup({ domain, token, groupId, offset, limit })
yield put({
type: actions.GROUPS_GET_ACTIVITIES_SUCCESS,
activities: jsonData.activity,
- total: jsonData.total,
+ groupId: groupId,
+ pagination: {
+ ...pagination,
+ total: jsonData.total,
+ },
});
} else {
yield put({
@@ -609,6 +598,65 @@ export function* getLocationListLastModifiedDate({ domain, token }) {
}
}
+export function* deleteComment({ domain, token, groupId, commentId }) {
+ const isConnected = yield select((state) => state.networkConnectivityReducer.isConnected);
+
+ yield put({ type: actions.GROUPS_DELETE_COMMENT_START });
+
+ yield put({
+ type: 'REQUEST',
+ payload: {
+ url: `https://${domain}/wp-json/dt-posts/v2/groups/${groupId}/comments/${commentId}`,
+ data: {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ },
+ isConnected,
+ action: actions.GROUPS_DELETE_COMMENT_RESPONSE,
+ },
+ });
+
+ try {
+ let response = yield take(actions.GROUPS_DELETE_COMMENT_RESPONSE);
+ response = response.payload;
+ let jsonData = response.data;
+ if (isConnected) {
+ if (response.status === 200) {
+ yield put({
+ type: actions.GROUPS_DELETE_COMMENT_SUCCESS,
+ groupId,
+ commentId,
+ });
+ } else {
+ yield put({
+ type: actions.GROUPS_DELETE_COMMENT_FAILURE,
+ error: {
+ code: jsonData.code,
+ message: jsonData.message,
+ },
+ });
+ }
+ } else {
+ yield put({
+ type: actions.GROUPS_DELETE_COMMENT_SUCCESS,
+ groupId,
+ commentId,
+ });
+ }
+ } catch (error) {
+ yield put({
+ type: actions.GROUPS_DELETE_COMMENT_FAILURE,
+ error: {
+ code: '400',
+ message: 'Unable to process the request. Please try again later.',
+ },
+ });
+ }
+}
+
export default function* groupsSaga() {
yield all([
takeEvery(actions.GROUPS_SAVE, saveGroup),
@@ -622,5 +670,6 @@ export default function* groupsSaga() {
takeEvery(actions.GROUPS_GET_SETTINGS, getSettings),
takeEvery(actions.GROUPS_LOCATIONS_SEARCH, searchLocations),
takeEvery(actions.GROUPS_LOCATIONS_MODIFIED_DATE, getLocationListLastModifiedDate),
+ takeEvery(actions.GROUPS_DELETE_COMMENT, deleteComment),
]);
}
diff --git a/store/sagas/networkConnectivity.sagas.js b/store/sagas/networkConnectivity.sagas.js
index c21e2fab..7bdbf50b 100644
--- a/store/sagas/networkConnectivity.sagas.js
+++ b/store/sagas/networkConnectivity.sagas.js
@@ -13,8 +13,8 @@ export default function* networkConnectivitySaga() {
...action,
};
// Only process POST and SAVE requests
- if (action.data.method === 'POST') {
- if (action.action.includes('SAVE')) {
+ if (action.data.method === 'POST' || action.data.method === 'DELETE') {
+ if (action.action.includes('SAVE') || action.action.includes('DELETE')) {
mappedRequest = {
...mappedRequest,
isConnected: true,
diff --git a/store/sagas/questionnaire.sagas.js b/store/sagas/questionnaire.sagas.js
new file mode 100644
index 00000000..a01262a9
--- /dev/null
+++ b/store/sagas/questionnaire.sagas.js
@@ -0,0 +1,156 @@
+import { put, take, all, takeEvery } from 'redux-saga/effects';
+import * as actions from '../actions/questionnaire.actions';
+
+export function* getActiveQuestionnaires({ domain, token }) {
+ yield put({ type: actions.GET_QUESTIONNAIRES_ACTIVE_START });
+
+ yield put({
+ type: 'REQUEST',
+ payload: {
+ url: `https://${domain}/wp-json/dt-questionnaire/v1/questionnaires`,
+ data: {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ },
+ action: actions.GET_QUESTIONNAIRES_ACTIVE_RESPONSE,
+ },
+ });
+
+ try {
+ let response = yield take(actions.GET_QUESTIONNAIRES_ACTIVE_RESPONSE);
+ response = response.payload;
+ const jsonData = response.data;
+ if (response.status === 200) {
+ if (jsonData) {
+ yield put({
+ type: actions.GET_QUESTIONNAIRES_ACTIVE_SUCCESS,
+ payload: jsonData,
+ });
+ }
+ } else {
+ yield put({
+ type: actions.GET_QUESTIONNAIRES_ACTIVE_FAILURE,
+ error: {
+ code: jsonData.code,
+ message: jsonData.message,
+ },
+ });
+ }
+ } catch (error) {
+ yield put({
+ type: actions.GET_QUESTIONNAIRES_ACTIVE_FAILURE,
+ error: {
+ code: '400',
+ message: 'Unable to process the request. Please try again later.',
+ },
+ });
+ }
+}
+
+export function* getQuestionnaireById({ domain, token, id }) {
+ yield put({ type: actions.GET_QUESTIONNAIRE_BY_ID_START });
+
+ yield put({
+ type: 'REQUEST',
+ payload: {
+ url: `https://${domain}/wp-json/dt-questionnaire/v1/questionnaires/${id}`,
+ data: {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ },
+ action: actions.GET_QUESTIONNAIRE_BY_ID_RESPONSE,
+ },
+ });
+
+ try {
+ let response = yield take(actions.GET_QUESTIONNAIRE_BY_ID_RESPONSE);
+ response = response.payload;
+ const jsonData = response.data;
+ if (response.status === 200) {
+ if (jsonData) {
+ yield put({
+ type: actions.GET_QUESTIONNAIRE_BY_ID_SUCCESS,
+ payload: jsonData,
+ });
+ }
+ } else {
+ yield put({
+ type: actions.GET_QUESTIONNAIRE_BY_ID_FAILURE,
+ error: {
+ code: jsonData.code,
+ message: jsonData.message,
+ },
+ });
+ }
+ } catch (error) {
+ yield put({
+ type: actions.GET_QUESTIONNAIRE_BY_ID_FAILURE,
+ error: {
+ code: '400',
+ message: 'Unable to process the request. Please try again later.',
+ },
+ });
+ }
+}
+
+export function* submitQuestionnaire({ domain, token, questionnaire }) {
+ yield put({ type: actions.SUBMIT_QUESTIONNAIRE_START });
+
+ yield put({
+ type: 'REQUEST',
+ payload: {
+ url: `https://${domain}/wp-json/dt-questionnaire/v1/submit`,
+ data: {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ body: JSON.stringify(questionnaire),
+ },
+ action: actions.SUBMIT_QUESTIONNAIRE_RESPONSE,
+ },
+ });
+
+ try {
+ let response = yield take(actions.SUBMIT_QUESTIONNAIRE_RESPONSE);
+ response = response.payload;
+ const jsonData = response.data;
+ if (response.status === 200) {
+ if (jsonData) {
+ yield put({
+ type: actions.SUBMIT_QUESTIONNAIRE_SUCCESS,
+ payload: jsonData,
+ });
+ }
+ } else {
+ yield put({
+ type: actions.SUBMIT_QUESTIONNAIRE_FAILURE,
+ error: {
+ code: jsonData.code,
+ message: jsonData.message,
+ },
+ });
+ }
+ } catch (error) {
+ yield put({
+ type: actions.SUBMIT_QUESTIONNAIRE_FAILURE,
+ error: {
+ code: '400',
+ message: 'Unable to process the request. Please try again later.',
+ },
+ });
+ }
+}
+
+export default function* questionnairesSaga() {
+ yield all([takeEvery(actions.GET_QUESTIONNAIRES_ACTIVE, getActiveQuestionnaires)]);
+ yield all([takeEvery(actions.GET_QUESTIONNAIRE_BY_ID, getQuestionnaireById)]);
+ yield all([takeEvery(actions.SUBMIT_QUESTIONNAIRE, submitQuestionnaire)]);
+}
diff --git a/store/sagas/request.sagas.js b/store/sagas/request.sagas.js
index 39815ada..3ca4d5fc 100644
--- a/store/sagas/request.sagas.js
+++ b/store/sagas/request.sagas.js
@@ -3,7 +3,7 @@
// -- https://redux-saga.js.org/docs/advanced/Channels.html
import { take, fork, call, put, race, actionChannel, select } from 'redux-saga/effects';
-import * as Sentry from 'sentry-expo';
+//import * as Sentry from 'sentry-expo';
function* sendRequest(url, data) {
let genericErrorResponse = {
@@ -13,7 +13,6 @@ function* sendRequest(url, data) {
message: 'Unable to process the request. Please try again later.',
},
};
-
const request = yield fetch(url, data)
.then((response) => {
if (response.status >= 200 && response.status < 300) {
@@ -40,11 +39,11 @@ function* sendRequest(url, data) {
var isHTML = RegExp.prototype.test.bind(/(<([^>]+)>)/i);
if (isHTML(errorJSON)) {
// Back-end error response in (HTML)
- Sentry.captureException(errorJSON);
+ //Sentry.captureException(errorJSON);
return genericErrorResponse;
} else {
// Back-end error response in (JSON)
- Sentry.captureException(errorJSON);
+ //Sentry.captureException(errorJSON);
errorJSON = JSON.parse(errorJSON);
return {
status: errorJSON.data && errorJSON.data.status ? errorJSON.data.status : '',
@@ -56,13 +55,13 @@ function* sendRequest(url, data) {
}
},
(error) => {
- Sentry.captureException(error);
+ //Sentry.captureException(error);
// Catch if 'text() method' or 'JSON.parse()' throw error
return genericErrorResponse;
},
);
} else {
- Sentry.captureException(error);
+ //Sentry.captureException(error);
// Catch if 'text() method' or 'JSON.parse()' throw error
return genericErrorResponse;
}
@@ -162,6 +161,12 @@ export default function* requestSaga() {
payload: { data: {}, status: 200 },
});
}
+ if (payload.data.method === 'DELETE' && payload.action.includes('DELETE')) {
+ // Offline entity delete (send "last request" as response)
+ /* eslint-disable */
+ yield put({ type: payload.action, payload: { data: true, status: 200 } });
+ /* eslint-enable */
+ }
}
}
} else if (request) {