12 |
13 |
14 | Architecture app project
15 | ------------------------------------
16 |
17 | It showcases a simple implementation of the Model-View-Presenter pattern.
18 | 
19 |
20 |
21 | Architecture backend services
22 | ------------------------------------
23 |
24 | 
25 |
26 |
27 | Libraries used on the app project
28 | ------------------------------------
29 |
30 | * [Retrofit 2][2]
31 | * [Glide][3]
32 |
33 |
34 | Services used on the backend services
35 | ------------------------------------
36 |
37 | * [Google App Angine][10]
38 | * [Google Cloud Endpoints][11]
39 | * [Google Cloud Storage][12]
40 | * [Google Cloud Datastore][13]
41 |
42 |
43 | Libraries used on the backend web
44 | ------------------------------------
45 |
46 | * [Angular JS 1.5][20]
47 | * [Bootstrap][21]
48 |
49 |
50 | Quality
51 | ------------------------------------
52 |
53 | The followings tools are used :
54 | - Checkstyle.
55 | - Findbugs.
56 | - PMD.
57 | - Lint.
58 |
59 |
60 | Screenshots app project
61 | ------------------------------------
62 |
63 | 
64 |
65 |
66 | License
67 | -------
68 |
69 | Copyright 2017 Thales Reis Machado Lima
70 |
71 | Licensed under the Apache License, Version 2.0 (the "License");
72 | you may not use this file except in compliance with the License.
73 | You may obtain a copy of the License at
74 |
75 | http://www.apache.org/licenses/LICENSE-2.0
76 |
77 | Unless required by applicable law or agreed to in writing, software
78 | distributed under the License is distributed on an "AS IS" BASIS,
79 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
80 | See the License for the specific language governing permissions and
81 | limitations under the License.
82 |
83 |
84 | [2]: http://square.github.io/retrofit/
85 | [3]: https://github.com/bumptech/glide/
86 |
87 | [10]: https://cloud.google.com/appengine/
88 | [11]: https://cloud.google.com/endpoints/
89 | [12]: https://cloud.google.com/storage/
90 | [13]: https://cloud.google.com/datastore/
91 |
92 | [20]: https://angularjs.org/
93 | [21]: http://getbootstrap.com/
94 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/fabric.properties:
--------------------------------------------------------------------------------
1 | #Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public.
2 | #Mon Apr 03 21:14:02 BRT 2017
3 | apiSecret=f8967c17eff5e9ff351c6a4ad5799807082d37884b9d62074e09c56040f16e55
4 |
--------------------------------------------------------------------------------
/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "463730165489",
4 | "firebase_url": "https://guideapp-3081b.firebaseio.com",
5 | "project_id": "guideapp-3081b",
6 | "storage_bucket": "guideapp-3081b.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:463730165489:android:4154ffce295f504a",
12 | "android_client_info": {
13 | "package_name": "eco.guideapp"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "463730165489-js7ce7p8jrj3so0e6bgett52dkr529tg.apps.googleusercontent.com",
19 | "client_type": 1,
20 | "android_info": {
21 | "package_name": "eco.guideapp",
22 | "certificate_hash": "efdd527bd0202a5699ae509edb28c3af3bfd41dd"
23 | }
24 | },
25 | {
26 | "client_id": "463730165489-gd7gcnatnbo1nt81becm7re22erippdc.apps.googleusercontent.com",
27 | "client_type": 3
28 | }
29 | ],
30 | "api_key": [
31 | {
32 | "current_key": "AIzaSyBZUObcLo1sbglzC8YBBmXUIT-0bskgTK0"
33 | }
34 | ],
35 | "services": {
36 | "analytics_service": {
37 | "status": 1
38 | },
39 | "appinvite_service": {
40 | "status": 2,
41 | "other_platform_oauth_client": [
42 | {
43 | "client_id": "463730165489-gd7gcnatnbo1nt81becm7re22erippdc.apps.googleusercontent.com",
44 | "client_type": 3
45 | }
46 | ]
47 | },
48 | "ads_service": {
49 | "status": 2
50 | }
51 | }
52 | }
53 | ],
54 | "configuration_version": "1"
55 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/thales/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/guideapp/data/TestUtilities.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.data;
2 |
3 | import android.database.ContentObserver;
4 | import android.net.Uri;
5 | import android.os.Handler;
6 | import android.os.HandlerThread;
7 |
8 | import com.guideapp.utils.PollingCheck;
9 |
10 | public class TestUtilities {
11 |
12 | static TestContentObserver getTestContentObserver() {
13 | return TestContentObserver.getTestContentObserver();
14 | }
15 |
16 | /**
17 | * Students: The test functions for insert and delete use TestContentObserver to test
18 | * the ContentObserver callbacks using the PollingCheck class from the Android Compatibility
19 | * Test Suite tests.
20 | * NOTE: This only tests that the onChange function is called; it DOES NOT test that the
21 | * correct Uri is returned.
22 | */
23 | static class TestContentObserver extends ContentObserver {
24 | final HandlerThread mHT;
25 | boolean mContentChanged;
26 |
27 | private TestContentObserver(HandlerThread ht) {
28 | super(new Handler(ht.getLooper()));
29 | mHT = ht;
30 | }
31 |
32 | static TestContentObserver getTestContentObserver() {
33 | HandlerThread ht = new HandlerThread("ContentObserverThread");
34 | ht.start();
35 | return new TestContentObserver(ht);
36 | }
37 |
38 | /**
39 | * Called when a content change occurs.
40 | *
41 | * To ensure correct operation on older versions of the framework that did not provide a
42 | * Uri argument, applications should also implement this method whenever they implement
43 | * the { #onChange(boolean, Uri)} overload.
44 | *
45 | * @param selfChange True if this is a self-change notification.
46 | */
47 | @Override
48 | public void onChange(boolean selfChange) {
49 | onChange(selfChange, null);
50 | }
51 |
52 | /**
53 | * Called when a content change occurs. Includes the changed content Uri when available.
54 | *
55 | * @param selfChange True if this is a self-change notification.
56 | * @param uri The Uri of the changed content, or null if unknown.
57 | */
58 | @Override
59 | public void onChange(boolean selfChange, Uri uri) {
60 | mContentChanged = true;
61 | }
62 |
63 | /**
64 | * Note: The PollingCheck class is taken from the Android CTS (Compatibility Test Suite).
65 | * It's useful to look at the Android CTS source for ideas on how to test your Android
66 | * applications. The reason that PollingCheck works is that, by default, the JUnit testing
67 | * framework is not running on the main Android application thread.
68 | */
69 | void waitForNotificationOrFail() {
70 |
71 | new PollingCheck(5000) {
72 | @Override
73 | protected boolean check() {
74 | return mContentChanged;
75 | }
76 | }.run();
77 | mHT.quit();
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/guideapp/utils/PollingCheck.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.utils;
2 |
3 |
4 | import junit.framework.Assert;
5 | import java.util.concurrent.Callable;
6 |
7 | public abstract class PollingCheck {
8 |
9 | private static final long TIME_SLICE = 50;
10 | private long mTimeout = 3000;
11 |
12 | public PollingCheck() {
13 | }
14 |
15 | public PollingCheck(long timeout) {
16 | mTimeout = timeout;
17 | }
18 |
19 | public static void check(CharSequence message, long timeout, Callable condition)
20 | throws Exception {
21 | while (timeout > 0) {
22 | if (condition.call()) {
23 | return;
24 | }
25 |
26 | Thread.sleep(TIME_SLICE);
27 | timeout -= TIME_SLICE;
28 | }
29 |
30 | Assert.fail(message.toString());
31 | }
32 |
33 | protected abstract boolean check();
34 |
35 | public void run() {
36 | if (check()) {
37 | return;
38 | }
39 |
40 | long timeout = mTimeout;
41 | while (timeout > 0) {
42 | try {
43 | Thread.sleep(TIME_SLICE);
44 | } catch (InterruptedException e) {
45 | Assert.fail("Notification error, unexpected InterruptedException");
46 | }
47 |
48 | if (check()) {
49 | return;
50 | }
51 |
52 | timeout -= TIME_SLICE;
53 | }
54 |
55 | Assert.fail("Notification not set, unexpected timeout");
56 | }
57 | }
--------------------------------------------------------------------------------
/app/src/main/ic_clear_gray-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/ic_clear_gray-web.png
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/App.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp
2 |
3 | import android.support.multidex.MultiDexApplication
4 |
5 | import com.facebook.stetho.Stetho
6 | import com.crashlytics.android.Crashlytics
7 | import io.fabric.sdk.android.Fabric
8 |
9 | class App : MultiDexApplication() {
10 | override fun onCreate() {
11 | super.onCreate()
12 | Fabric.with(this, Crashlytics())
13 |
14 | if (BuildConfig.DEBUG) {
15 | Stetho.initializeWithDefaults(this)
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/data/local/GuideDbHelper.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.data.local
2 |
3 | import android.content.Context
4 | import android.database.sqlite.SQLiteDatabase
5 | import android.database.sqlite.SQLiteOpenHelper
6 |
7 | class GuideDbHelper(context: Context) : SQLiteOpenHelper(context, GuideDbHelper.DATABASE_NAME, null, GuideDbHelper.DATABASE_VERSION) {
8 | override fun onCreate(db: SQLiteDatabase) {
9 | val sqlCreateLocalTable = "CREATE TABLE " + GuideContract.LocalEntry.TABLE_NAME + " (" +
10 | GuideContract.LocalEntry._ID + " INTEGER PRIMARY KEY, " +
11 | GuideContract.LocalEntry.COLUMN_DESCRIPTION + " TEXT, " +
12 | GuideContract.LocalEntry.COLUMN_SITE + " TEXT, " +
13 | GuideContract.LocalEntry.COLUMN_PHONE + " TEXT, " +
14 | GuideContract.LocalEntry.COLUMN_ADDRESS + " TEXT, " +
15 | GuideContract.LocalEntry.COLUMN_WIFI + " INTEGER, " +
16 | GuideContract.LocalEntry.COLUMN_DETAIL + " TEXT, " +
17 | GuideContract.LocalEntry.COLUMN_LATITUDE + " REAL, " +
18 | GuideContract.LocalEntry.COLUMN_LONGITUDE + " REAL, " +
19 | GuideContract.LocalEntry.COLUMN_IMAGE_PATH + " TEXT, " +
20 | GuideContract.LocalEntry.COLUMN_ID_CITY + " INTEGER, " +
21 | GuideContract.LocalEntry.COLUMN_ID_CATEGORY + " INTEGER, " +
22 | GuideContract.LocalEntry.COLUMN_ID_SUB_CATEGORY + " TEXT, " +
23 | GuideContract.LocalEntry.COLUMN_TIMESTAMP + " INTEGER, " +
24 | GuideContract.LocalEntry.COLUMN_DESCRIPTION_SUB_CATEGORY + " TEXT, " +
25 | GuideContract.LocalEntry.COLUMN_FAVORITE + " INTEGER "+" )"
26 |
27 | db.execSQL(sqlCreateLocalTable)
28 | }
29 |
30 | override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
31 | db.execSQL("DROP TABLE IF EXISTS " + GuideContract.LocalEntry.TABLE_NAME)
32 | onCreate(db)
33 | }
34 |
35 | companion object {
36 | private val DATABASE_NAME = "guide.db"
37 | private val DATABASE_VERSION = 1
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/data/remote/GuideApi.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.data.remote
2 |
3 | import com.guideapp.model.Local
4 | import com.guideapp.model.SubCategory
5 | import com.guideapp.model.wrapper.ListResponse
6 |
7 | import retrofit2.Call
8 | import retrofit2.http.GET
9 | import retrofit2.http.Query
10 |
11 | interface GuideApi {
12 |
13 | @GET("local")
14 | fun getLocals(
15 | @Query("idCity") idCity: Long?,
16 | @Query("idCategory") idCategory: Long?,
17 | @Query("idSubCategories") idSubCategory: LongArray): Call>
18 |
19 | @GET("local")
20 | fun getLocals(
21 | @Query("idCity") idCity: Long?): Call>
22 |
23 | @GET("subcategory")
24 | fun getSubCategories(@Query("idCategory") idCategory: Long): Call>
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/data/remote/RestClient.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.data.remote
2 |
3 | import com.guideapp.BuildConfig
4 |
5 | import java.util.concurrent.TimeUnit
6 |
7 | import okhttp3.OkHttpClient
8 | import okhttp3.logging.HttpLoggingInterceptor
9 | import retrofit2.Retrofit
10 | import retrofit2.converter.gson.GsonConverterFactory
11 |
12 | object RestClient {
13 | private var mGuideApi: GuideApi? = null
14 | private val TIMEOUT = 30
15 |
16 | val client: GuideApi
17 | get() {
18 | if (mGuideApi == null) {
19 | val client = Retrofit.Builder()
20 | .baseUrl(BuildConfig.ENDPOINT_URL)
21 | .client(okHttpClient)
22 | .addConverterFactory(GsonConverterFactory.create())
23 | .build()
24 |
25 | mGuideApi = client.create(GuideApi::class.java)
26 | }
27 |
28 | return mGuideApi!!
29 | }
30 |
31 |
32 | private val okHttpClient: OkHttpClient
33 | get() {
34 | val okClientBuilder = OkHttpClient.Builder()
35 |
36 | val httpLoggingInterceptor = HttpLoggingInterceptor()
37 | httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BASIC
38 | okClientBuilder.addInterceptor(httpLoggingInterceptor)
39 | okClientBuilder.connectTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
40 | okClientBuilder.readTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
41 | okClientBuilder.writeTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
42 | return okClientBuilder.build()
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/model/Local.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.model
2 |
3 | data class Local(var id: Long? = null,
4 | var description: String? = null,
5 | var site: String? = null,
6 | var phone: String? = null,
7 | var address: String? = null,
8 | var isWifi: Boolean = false,
9 | var detail: String? = null,
10 | var latitude: Double = 0.toDouble(),
11 | var longitude: Double = 0.toDouble(),
12 | var imagePath: String? = null,
13 | var idCity: Long? = null,
14 | var idCategory: Long = 0,
15 | var idCategories: List? = null,
16 | var idSubCategories: List? = null,
17 | var timestamp: Long = 0,
18 | var subCategories: List? = null,
19 | var descriptionSubCategories: String? = null,
20 | var isFavorite: Boolean = false
21 | )
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/model/MainMenu.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.model
2 |
3 | data class MainMenu(val id: Long,
4 | val idTitle: Int,
5 | val idImage: Int,
6 | val idColorPrimary: Int)
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/model/SubCategory.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.model
2 |
3 | data class SubCategory(val id: Long? = null,
4 | val description: String? = null,
5 | val idCategory: Long? = null,
6 | val timestamp: Long? = null)
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/model/wrapper/ListResponse.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.model.wrapper
2 |
3 | data class ListResponse(var items: List? = null)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/sync/GuideFirebaseJobService.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.sync
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.os.AsyncTask
6 |
7 | import com.firebase.jobdispatcher.JobParameters
8 | import com.firebase.jobdispatcher.JobService
9 |
10 | class GuideFirebaseJobService : JobService() {
11 | private var mFetchGuideTask: AsyncTask? = null
12 |
13 | @SuppressLint("StaticFieldLeak")
14 | override fun onStartJob(jobParameters: JobParameters): Boolean {
15 |
16 | mFetchGuideTask = object : AsyncTask() {
17 | override fun doInBackground(vararg voids: Void): Void? {
18 | val context = applicationContext
19 | GuideSyncTask.syncGuide(context)
20 | jobFinished(jobParameters, false)
21 | return null
22 | }
23 |
24 | override fun onPostExecute(aVoid: Void) {
25 | jobFinished(jobParameters, false)
26 | }
27 | }
28 |
29 | mFetchGuideTask?.execute()
30 | return true
31 | }
32 |
33 | override fun onStopJob(jobParameters: JobParameters): Boolean {
34 | mFetchGuideTask?.cancel(true)
35 | return true
36 | }
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/sync/GuideSyncIntentService.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.sync
2 |
3 | import android.app.IntentService
4 | import android.content.Intent
5 |
6 | class GuideSyncIntentService : IntentService("GuideSyncIntentService") {
7 | override fun onHandleIntent(intent: Intent?) {
8 | GuideSyncTask.syncGuide(this)
9 | }
10 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views
2 |
3 | import android.os.Bundle
4 | import android.support.v7.app.AppCompatActivity
5 |
6 | abstract class BaseActivity : AppCompatActivity() {
7 | override fun onCreate(savedInstanceState: Bundle?) {
8 | super.onCreate(savedInstanceState)
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/GridSpacingItemDecoration.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views
2 |
3 | import android.graphics.Rect
4 | import android.support.v7.widget.RecyclerView
5 | import android.view.View
6 |
7 | class GridSpacingItemDecoration(private val mSpanCount: Int, private val mSpacing: Int, private val mIncludeEdge: Boolean) : RecyclerView.ItemDecoration() {
8 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView,
9 | state: RecyclerView.State?) {
10 | val position = parent.getChildAdapterPosition(view) // item position
11 | val column = position % mSpanCount // item column
12 | if (mIncludeEdge) {
13 | outRect.left = mSpacing - column * mSpacing / mSpanCount
14 | outRect.right = (column + 1) * mSpacing / mSpanCount
15 | if (position < mSpanCount) { // top edge
16 | outRect.top = mSpacing
17 | }
18 | outRect.bottom = mSpacing // item bottom
19 | } else {
20 | outRect.left = column * mSpacing / mSpanCount // column * ((1f / spanCount) * spacing)
21 | outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount
22 | if (position >= mSpanCount) {
23 | outRect.top = mSpacing // item top
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/favorite/FavoriteAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.favorite
2 |
3 | import android.content.Context
4 | import android.support.v7.widget.RecyclerView
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.ImageView
9 | import android.widget.TextView
10 |
11 | import com.bumptech.glide.Glide
12 | import com.bumptech.glide.load.engine.DiskCacheStrategy
13 | import com.guideapp.R
14 | import com.guideapp.model.Local
15 |
16 | import java.util.ArrayList
17 |
18 | internal class FavoriteAdapter(private val mContext: Context, private val mListener: FavoriteAdapter.ItemClickListener) : RecyclerView.Adapter() {
19 | private val mDataSet: MutableList
20 |
21 | internal interface ItemClickListener {
22 | fun onItemClick(item: Local, view: ImageView)
23 | }
24 |
25 | init {
26 | this.mDataSet = ArrayList()
27 | }
28 |
29 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteAdapter.LocalViewHolder {
30 | val v = LayoutInflater.from(parent.context).inflate(R.layout.item_local_favorite, parent, false)
31 | return LocalViewHolder(v)
32 | }
33 |
34 | override fun onBindViewHolder(holder: FavoriteAdapter.LocalViewHolder, position: Int) {
35 | holder.populate(mDataSet[position])
36 | }
37 |
38 | override fun getItemCount(): Int {
39 | return mDataSet.size
40 | }
41 |
42 | fun replaceData(dataSet: List) {
43 | setList(dataSet)
44 | notifyDataSetChanged()
45 | }
46 |
47 | private fun setList(dataSet: List) {
48 | mDataSet.clear()
49 | mDataSet.addAll(dataSet)
50 | }
51 |
52 | internal inner class LocalViewHolder(private val mView: View) : RecyclerView.ViewHolder(mView) {
53 | private val mPhotoView: ImageView = mView.findViewById(R.id.local_picture) as ImageView
54 | private val mDescriptionView: TextView = mView.findViewById(R.id.local_text) as TextView
55 | private val mAddressView: TextView = mView.findViewById(R.id.local_address) as TextView
56 | private val mDescriptionsSubCategory: TextView = mView.findViewById(R.id.descriptions_sub_category) as TextView
57 | private var mItem: Local? = null
58 |
59 | init {
60 | mView.setOnClickListener { mItem?.let { it1 -> mListener.onItemClick(it1, mPhotoView) } }
61 | }
62 |
63 | fun populate(data: Local) {
64 | mItem = data
65 | mDescriptionView.text = data.description
66 | mAddressView.text = data.address
67 | mDescriptionsSubCategory.text = data.descriptionSubCategories
68 |
69 | Glide.with(mContext)
70 | .load(data.imagePath)
71 | .placeholder(R.color.placeholder)
72 | .diskCacheStrategy(DiskCacheStrategy.ALL)
73 | .into(mPhotoView)
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/favorite/FavoriteContract.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.favorite
2 |
3 | import android.content.Context
4 | import android.support.v4.app.LoaderManager
5 | import android.widget.ImageView
6 |
7 | import com.guideapp.model.Local
8 |
9 | internal interface FavoriteContract {
10 | interface View {
11 | fun showNoItemsMessage()
12 |
13 | fun hideNoItemsMessage()
14 |
15 | fun showLocals(locals: List)
16 |
17 | fun showLocalDetailUi(local: Local, view: ImageView)
18 |
19 | fun getContext(): Context
20 | }
21 |
22 | interface Presenter {
23 | fun loadLocals(loaderManager: LoaderManager)
24 |
25 | fun onResume(loaderManager: LoaderManager)
26 |
27 | fun openLocalDetails(local: Local, view: ImageView)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/favorite/FavoriteFragment.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.favorite
2 |
3 | import android.os.Bundle
4 | import android.support.v4.app.Fragment
5 | import android.support.v7.widget.LinearLayoutManager
6 | import android.support.v7.widget.RecyclerView
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.ImageView
11 | import android.widget.TextView
12 |
13 | import com.guideapp.R
14 | import com.guideapp.model.Local
15 | import com.guideapp.ui.views.localdetail.LocalDetailActivity
16 | import com.guideapp.ui.views.DividerItemDecoration
17 |
18 | class FavoriteFragment : Fragment(), FavoriteContract.View, FavoriteAdapter.ItemClickListener {
19 | private var mAdapter: FavoriteAdapter? = null
20 | private var mPresenter: FavoriteContract.Presenter? = null
21 | private var mMessageView: TextView? = null
22 |
23 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
24 | savedInstanceState: Bundle?): View? {
25 |
26 | val view = inflater!!.inflate(R.layout.fragment_favorite, container, false)
27 | setupRecyclerView(view)
28 | setupViews(view)
29 | return view
30 | }
31 |
32 | private fun setupViews(view: View) {
33 | mMessageView = view.findViewById(R.id.message_view) as TextView
34 | }
35 |
36 | override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
37 | super.onViewCreated(view, savedInstanceState)
38 |
39 | mPresenter = FavoritePresenter(this)
40 | mPresenter?.loadLocals(activity.supportLoaderManager)
41 | }
42 |
43 | private fun setupRecyclerView(view: View) {
44 | mAdapter = FavoriteAdapter(context, this)
45 | val recyclerView = view.findViewById(R.id.recycler) as RecyclerView
46 |
47 | recyclerView.layoutManager = LinearLayoutManager(context)
48 | recyclerView.adapter = mAdapter
49 | recyclerView.addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL_LIST))
50 | }
51 |
52 | override fun onResume() {
53 | super.onResume()
54 | mPresenter?.onResume(activity.supportLoaderManager)
55 | }
56 |
57 | override fun showNoItemsMessage() {
58 | mMessageView?.visibility = View.VISIBLE
59 | }
60 |
61 | override fun hideNoItemsMessage() {
62 | mMessageView?.visibility = View.GONE
63 | }
64 |
65 | override fun onItemClick(item: Local, view: ImageView) {
66 | mPresenter?.openLocalDetails(item, view)
67 | }
68 |
69 | override fun showLocals(locals: List) {
70 | mAdapter?.replaceData(locals)
71 | }
72 |
73 | override fun showLocalDetailUi(local: Local, view: ImageView) {
74 | local.id?.let { LocalDetailActivity.navigate(activity, view, it, local.idCategory) }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/favorite/FavoritePresenter.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.favorite
2 |
3 | import android.database.Cursor
4 | import android.os.Bundle
5 | import android.support.v4.app.LoaderManager
6 | import android.support.v4.content.CursorLoader
7 | import android.support.v4.content.Loader
8 | import android.widget.ImageView
9 |
10 | import com.guideapp.data.local.GuideContract
11 | import com.guideapp.model.Local
12 | import com.guideapp.utilities.DataUtil
13 |
14 | import java.util.ArrayList
15 |
16 | internal class FavoritePresenter(private val mView: FavoriteContract.View) : FavoriteContract.Presenter, LoaderManager.LoaderCallbacks {
17 | override fun loadLocals(loaderManager: LoaderManager) {
18 | loaderManager.initLoader(ID_LOADER, Bundle.EMPTY, this)
19 | }
20 |
21 | override fun onResume(loaderManager: LoaderManager) {
22 | loaderManager.restartLoader(ID_LOADER, Bundle.EMPTY, this)
23 | }
24 |
25 | override fun openLocalDetails(local: Local, view: ImageView) {
26 | this.mView.showLocalDetailUi(local, view)
27 | }
28 |
29 | override fun onCreateLoader(id: Int, args: Bundle): Loader {
30 | when (id) {
31 | ID_LOADER -> return CursorLoader(mView.getContext(),
32 | GuideContract.LocalEntry.CONTENT_URI, null,
33 | GuideContract.LocalEntry.getSqlSelectForFavorites(), null, null)
34 |
35 | else -> throw RuntimeException("Loader Not Implemented: " + id)
36 | }
37 | }
38 |
39 | override fun onLoadFinished(loader: Loader, data: Cursor) {
40 | if (data.count > 0) {
41 | mView.showLocals(DataUtil.getLocalsFromCursor(data))
42 | mView.hideNoItemsMessage()
43 | } else {
44 | mView.showLocals(ArrayList())
45 | mView.showNoItemsMessage()
46 | }
47 | }
48 |
49 | override fun onLoaderReset(loader: Loader) {
50 | mView.showLocals(ArrayList())
51 | }
52 |
53 | companion object {
54 | private val ID_LOADER = 333
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/local/LocalAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.local
2 |
3 | import android.support.v7.widget.RecyclerView
4 | import android.view.ViewGroup
5 | import android.widget.ImageView
6 | import com.bumptech.glide.Glide
7 | import com.bumptech.glide.load.engine.DiskCacheStrategy
8 | import com.guideapp.R
9 | import com.guideapp.model.Local
10 | import com.guideapp.utilities.inflate
11 | import kotlinx.android.synthetic.main.item_local.view.*
12 | import java.util.*
13 |
14 | internal class LocalAdapter(private val mListener: LocalAdapter.ItemClickListener) : RecyclerView.Adapter() {
15 | private val mDataSet: MutableList = ArrayList()
16 |
17 | internal interface ItemClickListener {
18 | fun onItemClick(item: Local, view: ImageView)
19 | }
20 |
21 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocalViewHolder {
22 | return LocalViewHolder(parent)
23 | }
24 |
25 | override fun onBindViewHolder(holder: LocalViewHolder, position: Int) {
26 | holder.bind(mDataSet[position])
27 | }
28 |
29 | override fun getItemCount(): Int {
30 | return mDataSet.size
31 | }
32 |
33 | fun replaceData(dataSet: List) {
34 | setList(dataSet)
35 | notifyDataSetChanged()
36 | }
37 |
38 | private fun setList(dataSet: List) {
39 | mDataSet.clear()
40 | mDataSet.addAll(dataSet)
41 | }
42 |
43 | internal inner class LocalViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(parent.inflate(R.layout.item_local)) {
44 | private var mItem: Local? = null
45 |
46 | fun bind(item: Local) = with(itemView) {
47 | mItem = item
48 | local_text.text = item.description
49 | local_address.text = item.address
50 | descriptions_sub_category.text = item.descriptionSubCategories
51 |
52 | Glide.with(itemView.context)
53 | .load(item.imagePath)
54 | .placeholder(R.color.placeholder)
55 | .diskCacheStrategy(DiskCacheStrategy.ALL)
56 | .into(local_picture)
57 |
58 | itemView.setOnClickListener { mItem?.let { it1 -> mListener.onItemClick(it1, local_picture) } }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/local/LocalContract.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.local
2 |
3 | import android.content.Context
4 | import android.support.v4.app.LoaderManager
5 | import android.widget.ImageView
6 |
7 | import com.guideapp.model.Local
8 |
9 | internal interface LocalContract {
10 | interface View {
11 | fun showLocals(locals: List)
12 |
13 | fun showLocalDetailUi(local: Local, view: ImageView)
14 |
15 | fun showProgressBar()
16 |
17 | fun hideProgressBar()
18 |
19 | fun getContext(): Context
20 | }
21 |
22 | interface Presenter {
23 | fun loadLocals(loaderManager: LoaderManager)
24 |
25 | fun restartLoadLocals(loaderManager: LoaderManager, idCategory: Long)
26 |
27 | fun openLocalDetails(local: Local, view: ImageView)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/local/LocalPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.local
2 |
3 | import android.database.Cursor
4 | import android.os.Bundle
5 | import android.support.v4.app.LoaderManager
6 | import android.support.v4.content.CursorLoader
7 | import android.support.v4.content.Loader
8 | import android.widget.ImageView
9 |
10 | import com.guideapp.data.local.GuideContract
11 | import com.guideapp.model.Local
12 | import com.guideapp.utilities.DataUtil
13 |
14 | import java.util.ArrayList
15 |
16 | internal class LocalPresenter(private val mView: LocalContract.View, private var mIdCategory: Long) : LocalContract.Presenter, LoaderManager.LoaderCallbacks {
17 | override fun loadLocals(loaderManager: LoaderManager) {
18 | mView.showProgressBar()
19 | loaderManager.initLoader(ID_LOADER, Bundle.EMPTY, this)
20 | }
21 |
22 | override fun restartLoadLocals(loaderManager: LoaderManager, idCategory: Long) {
23 | if (this.mIdCategory == 0L) {
24 | loaderManager.destroyLoader(ID_LOADER)
25 | this.mIdCategory = idCategory
26 | loadLocals(loaderManager)
27 | }
28 | }
29 |
30 | override fun openLocalDetails(local: Local, view: ImageView) {
31 | this.mView.showLocalDetailUi(local, view)
32 | }
33 |
34 | override fun onCreateLoader(id: Int, args: Bundle): Loader {
35 | when (id) {
36 | ID_LOADER -> return CursorLoader(mView.getContext(),
37 | GuideContract.LocalEntry.CONTENT_URI, null,
38 | GuideContract.LocalEntry.getSqlSelectForIdCategory(mIdCategory), null, null)
39 | else -> throw RuntimeException("Loader Not Implemented: " + id)
40 | }
41 | }
42 |
43 | override fun onLoadFinished(loader: Loader, data: Cursor) {
44 | mView.hideProgressBar()
45 | mView.showLocals(DataUtil.getLocalsFromCursor(data))
46 | }
47 |
48 | override fun onLoaderReset(loader: Loader) {
49 | mView.showLocals(ArrayList())
50 | mView.hideProgressBar()
51 | }
52 |
53 | companion object {
54 | private val ID_LOADER = 356
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/localdetail/LocalDetailContract.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.localdetail
2 |
3 | import android.content.Context
4 | import android.support.v4.app.LoaderManager
5 |
6 | internal interface LocalDetailContract {
7 | interface View {
8 | fun showFavoriteYes()
9 |
10 | fun showFavoriteNo()
11 |
12 | fun showSnackbarRemoveFavorite()
13 |
14 | fun showSnackbarSaveFavorite()
15 |
16 | fun shareText(textToShare: String)
17 |
18 | fun getContext(): Context
19 |
20 | fun showTitle(description: String)
21 |
22 | fun showImage(imagePath: String)
23 |
24 | fun showCategory(text: String)
25 |
26 | fun showWebSiteAction()
27 |
28 | fun showDirectionAction()
29 |
30 | fun showCallAction()
31 |
32 | fun showCall(phone: String)
33 |
34 | fun showDetail(description: String)
35 |
36 | fun showAddress(address: String)
37 |
38 | fun showMap(latitude: Double, longitude: Double, idImageMarker: Int)
39 |
40 | fun dialPhoneNumber(number: String)
41 |
42 | fun openPage(url: String)
43 |
44 | fun openDirection(description: String, latLng: String)
45 | }
46 |
47 | interface Presenter {
48 | fun loadLocal(loaderManager: LoaderManager)
49 |
50 | fun destroy(loaderManager: LoaderManager)
51 |
52 | fun saveOrRemoveFavorite()
53 |
54 | fun shareLocal()
55 |
56 | fun loadWebsite()
57 |
58 | fun loadCall()
59 |
60 | fun loadDirection()
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/map/MapActivity.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.map
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import android.support.v4.app.Fragment
7 | import com.guideapp.R
8 | import com.guideapp.ui.views.BaseActivity
9 | import kotlinx.android.synthetic.main.toolbar_transparent.*
10 |
11 |
12 | class MapActivity : BaseActivity() {
13 | private var mIdCity: Long = 0
14 | private var mIdCategory: Long = 0
15 | private var mIdTitle: Int = 0
16 | private var mIdSubCategories: LongArray? = null
17 |
18 | override fun onCreate(savedInstanceState: Bundle?) {
19 | super.onCreate(savedInstanceState)
20 | setContentView(R.layout.activity_map)
21 | initExtra()
22 | setupToolbar()
23 | setupFragment(MapFragment.newInstance(mIdCity, mIdCategory, mIdSubCategories))
24 | }
25 |
26 | private fun initExtra() {
27 | mIdCity = intent.getLongExtra(EXTRA_CITY, 0)
28 | mIdCategory = intent.getLongExtra(EXTRA_CATEGORY, 0)
29 | mIdTitle = intent.getIntExtra(EXTRA_ID_TITLE, 0)
30 | mIdSubCategories = intent.getLongArrayExtra(EXTRA_SUB_CATEGORY)
31 | }
32 |
33 | private fun setupFragment(fragment: Fragment) {
34 | val fragmentManager = supportFragmentManager
35 | val transaction = fragmentManager.beginTransaction()
36 | transaction.add(R.id.contentFrame, fragment)
37 | transaction.commit()
38 | }
39 |
40 | private fun setupToolbar() {
41 | setSupportActionBar(toolbar)
42 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
43 | supportActionBar?.setTitle(R.string.app_name_city)
44 |
45 | if (mIdTitle > 0) {
46 | setTitle(mIdTitle)
47 | }
48 | }
49 |
50 | companion object {
51 | private val EXTRA_CITY = "id-city"
52 | private val EXTRA_CATEGORY = "id-category"
53 | private val EXTRA_SUB_CATEGORY = "id-sub-category"
54 | private val EXTRA_ID_TITLE = "id-title"
55 |
56 | fun navigate(context: Context, idCity: Long?) {
57 | val intent = Intent(context, MapActivity::class.java)
58 | intent.putExtra(EXTRA_CITY, idCity)
59 | context.startActivity(intent)
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/map/MapContract.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.map
2 |
3 | import android.content.Context
4 | import android.support.v4.app.LoaderManager
5 | import android.widget.ImageView
6 |
7 | import com.guideapp.model.Local
8 |
9 | internal interface MapContract {
10 | interface View {
11 | fun showLocals(locals: List)
12 |
13 | fun showLocalSummary(local: Local)
14 |
15 | fun showLocalDetailUi(local: Local, view: ImageView)
16 |
17 | fun getContext() : Context
18 | }
19 |
20 | interface Presenter {
21 | fun loadLocals(loaderManager: LoaderManager)
22 |
23 | fun openLocalSummary(local: Local?)
24 |
25 | fun openLocalDetails(local: Local, view: ImageView)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/map/MapPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.map
2 |
3 | import android.database.Cursor
4 | import android.os.Bundle
5 | import android.support.v4.app.LoaderManager
6 | import android.support.v4.content.CursorLoader
7 | import android.support.v4.content.Loader
8 | import android.widget.ImageView
9 |
10 | import com.guideapp.data.local.GuideContract
11 | import com.guideapp.model.Local
12 | import com.guideapp.utilities.DataUtil
13 |
14 | import java.util.ArrayList
15 |
16 | internal class MapPresenter(private val mView: MapContract.View) : MapContract.Presenter, LoaderManager.LoaderCallbacks {
17 | override fun loadLocals(loaderManager: LoaderManager) {
18 | loaderManager.initLoader(ID_LOADER, Bundle.EMPTY, this)
19 | }
20 |
21 | override fun openLocalSummary(local: Local?) {
22 | local?.let { mView.showLocalSummary(it) }
23 | }
24 |
25 | override fun openLocalDetails(local: Local, view: ImageView) {
26 | mView.showLocalDetailUi(local, view)
27 | }
28 |
29 | override fun onCreateLoader(id: Int, args: Bundle): Loader {
30 | when (id) {
31 | ID_LOADER -> return CursorLoader(mView.getContext(), GuideContract.LocalEntry.CONTENT_URI, null, null, null, null)
32 | else -> throw RuntimeException("Loader Not Implemented: " + id)
33 | }
34 | }
35 |
36 | override fun onLoadFinished(loader: Loader, data: Cursor) {
37 | mView.showLocals(DataUtil.getLocalsFromCursor(data))
38 | }
39 |
40 | override fun onLoaderReset(loader: Loader) {
41 | mView.showLocals(ArrayList())
42 | }
43 |
44 | companion object {
45 | private val ID_LOADER = 256
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/menu/MenuAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.menu
2 |
3 | import android.support.v7.widget.RecyclerView
4 | import android.view.ViewGroup
5 | import com.guideapp.R
6 | import com.guideapp.model.MainMenu
7 | import com.guideapp.utilities.inflate
8 | import kotlinx.android.synthetic.main.item_menu.view.*
9 |
10 | internal class MenuAdapter(private val mDataSet: List,
11 | private val mListener: MenuAdapter.RecyclerViewItemClickListener?) : RecyclerView.Adapter() {
12 | internal interface RecyclerViewItemClickListener {
13 | fun onItemClick(item: MainMenu)
14 | }
15 |
16 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
17 | return ViewHolder(parent)
18 | }
19 |
20 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
21 | holder.bind(mDataSet[position])
22 | }
23 |
24 | override fun getItemCount(): Int {
25 | return mDataSet.size
26 | }
27 |
28 | internal inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(parent.inflate(R.layout.item_menu)) {
29 | private var mItem: MainMenu? = null
30 |
31 | fun bind(item: MainMenu) = with(itemView) {
32 | mItem = item
33 | menu_item.setBackgroundResource(item.idColorPrimary)
34 | menu_title.setText(item.idTitle)
35 | menu_image.setImageResource(item.idImage)
36 | itemView.setOnClickListener { mItem?.let { it1 -> mListener?.onItemClick(it1) } }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/views/menu/MenuFragment.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.views.menu
2 |
3 |
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.support.v7.widget.GridLayoutManager
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 |
11 | import com.guideapp.R
12 | import com.guideapp.model.MainMenu
13 | import com.guideapp.ui.views.GridSpacingItemDecoration
14 | import com.guideapp.ui.views.local.LocalActivity
15 | import com.guideapp.ui.views.map.MapActivity
16 | import com.guideapp.utilities.Constants
17 | import com.guideapp.utilities.Utility
18 | import kotlinx.android.synthetic.main.fragment_menu.*
19 |
20 | class MenuFragment : Fragment(), MenuAdapter.RecyclerViewItemClickListener {
21 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
22 | return inflater?.inflate(R.layout.fragment_menu, container, false)
23 | }
24 |
25 | override fun onActivityCreated(savedInstanceState: Bundle?) {
26 | super.onActivityCreated(savedInstanceState)
27 | setupRecyclerView()
28 | }
29 |
30 | private fun setupRecyclerView() {
31 | recycler.layoutManager = GridLayoutManager(this.activity, 2)
32 | val adapter = MenuAdapter(Utility.menus, this)
33 | recycler.adapter = adapter
34 | recycler.addItemDecoration(GridSpacingItemDecoration(2, 16, true))
35 | }
36 |
37 | override fun onItemClick(item: MainMenu) {
38 | if (item.id == 1L) {
39 | MapActivity.navigate(this.activity, Constants.City.ID)
40 | return
41 | }
42 | LocalActivity.navigate(this.activity, item.id, item.idTitle)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/ui/widget/LocalFavoriteWidget.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.ui.widget
2 |
3 | import android.app.PendingIntent
4 | import android.appwidget.AppWidgetManager
5 | import android.appwidget.AppWidgetProvider
6 | import android.content.ComponentName
7 | import android.content.Context
8 | import android.content.Intent
9 | import android.support.v4.app.TaskStackBuilder
10 | import android.widget.RemoteViews
11 |
12 | import com.guideapp.R
13 | import com.guideapp.ui.views.localdetail.LocalDetailActivity
14 | import com.guideapp.ui.views.main.MainActivity
15 | import com.guideapp.utilities.Constants
16 |
17 | class LocalFavoriteWidget : AppWidgetProvider() {
18 |
19 | private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
20 | val views = RemoteViews(context.packageName, R.layout.widget_detail)
21 | val intent = Intent(context, MainActivity::class.java)
22 | val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
23 | views.setOnClickPendingIntent(R.id.widget, pendingIntent)
24 | setRemoteAdapter(context, views)
25 | val clickPendingIntentTemplate = TaskStackBuilder.create(context)
26 | .addNextIntentWithParentStack(Intent(context, LocalDetailActivity::class.java))
27 | .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
28 | views.setPendingIntentTemplate(R.id.widget_list, clickPendingIntentTemplate)
29 | views.setEmptyView(R.id.widget_list, R.id.widget_empty)
30 | appWidgetManager.updateAppWidget(appWidgetId, views)
31 | }
32 |
33 | private fun setRemoteAdapter(context: Context, views: RemoteViews) {
34 | views.setRemoteAdapter(R.id.widget_list, Intent(context, LocalFavoriteWidgetRemoteViewsService::class.java))
35 | }
36 |
37 | override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
38 | for (appWidgetId in appWidgetIds) {
39 | updateAppWidget(context, appWidgetManager, appWidgetId)
40 | }
41 | }
42 |
43 | override fun onReceive(context: Context, intent: Intent) {
44 | super.onReceive(context, intent)
45 | if (Constants.ACTION_DATA_UPDATED == intent.action) {
46 | val appWidgetManager = AppWidgetManager.getInstance(context)
47 | val appWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, javaClass))
48 | appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list)
49 | }
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/utilities/Constants.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.utilities
2 |
3 | object Constants {
4 | const val ACTION_DATA_UPDATED = "com.guideapp.ACTION_DATA_UPDATED"
5 | const val ACTION_DATA_SYNC_ERROR = "com.guideapp.ACTION_DATA_SYNC_ERROR"
6 |
7 | interface City {
8 | companion object {
9 | const val ID = 5659118702428160L
10 | const val LATITUDE = -20.3449802
11 | const val LONGITUDE = -46.8551188
12 | }
13 | }
14 |
15 | internal interface Menu {
16 | companion object {
17 | const val ALIMENTATION = 5684666375864320L
18 | const val ATTRACTIVE = 5651124426113024L
19 | const val ACCOMMODATION = 5679413765079040L
20 | }
21 | }
22 |
23 | interface Analytics {
24 | companion object {
25 | const val SAVE_FAVORITE = "save_favorite"
26 | const val REMOVE_FAVORITE = "remove_favorite"
27 | const val SCREEN = "screen"
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/utilities/Extensions.kt:
--------------------------------------------------------------------------------
1 | @file:JvmName("ExtensionsUtils")
2 |
3 | package com.guideapp.utilities
4 |
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 |
9 | fun ViewGroup.inflate(layoutId: Int, attachToRoot: Boolean = false): View {
10 | return LayoutInflater.from(context).inflate(layoutId, this, attachToRoot)
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/utilities/Utility.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.utilities
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.net.ConnectivityManager
6 |
7 | import com.guideapp.R
8 | import com.guideapp.model.Local
9 | import com.guideapp.model.MainMenu
10 |
11 | import java.util.ArrayList
12 |
13 | object Utility {
14 | fun isNetworkAvailable(c: Context): Boolean {
15 | val cm = c.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
16 |
17 | val activeNetwork = cm.activeNetworkInfo
18 | return activeNetwork != null && activeNetwork.isConnectedOrConnecting
19 | }
20 |
21 | fun updateWidgets(context: Context) {
22 | val dataUpdatedIntent = Intent(Constants.ACTION_DATA_UPDATED).setPackage(context.packageName)
23 | context.sendBroadcast(dataUpdatedIntent)
24 | }
25 |
26 | fun getTextToShare(context: Context, local: Local): String {
27 | return context.getString(R.string.share_text,
28 | local.description,
29 | local.address,
30 | local.descriptionSubCategories,
31 | "http://maps.google.com/maps?saddr=" + local.latitude + "," + local.longitude)
32 | }
33 |
34 |
35 | fun getIdDescriptionCategory(id: Long): Int {
36 | if (id == Constants.Menu.ACCOMMODATION) {
37 | return R.string.menu_accommodation
38 | }
39 |
40 | if (id == Constants.Menu.ALIMENTATION) {
41 | return R.string.menu_alimentation
42 | }
43 |
44 | if (id == Constants.Menu.ATTRACTIVE) {
45 | return R.string.menu_attractive
46 | }
47 |
48 | return 0
49 | }
50 |
51 | fun getIdImageCategory(id: Long): Int {
52 | if (id == Constants.Menu.ACCOMMODATION) {
53 | return R.drawable.ic_place_hotel_48dp
54 | }
55 |
56 | if (id == Constants.Menu.ALIMENTATION) {
57 | return R.drawable.ic_place_dining_48dp
58 | }
59 |
60 | if (id == Constants.Menu.ATTRACTIVE) {
61 | return R.drawable.ic_place_terrain_48dp
62 | }
63 |
64 | return 0
65 | }
66 |
67 | val menus: List
68 | get() {
69 | val menus = ArrayList()
70 | menus.add(MainMenu(1, R.string.menu_local, R.drawable.ic_map_white_36dp, R.color.green_500))
71 | menus.add(MainMenu(Constants.Menu.ALIMENTATION, R.string.menu_alimentation, R.drawable.ic_local_dining_white_36dp, R.color.blue_500))
72 | menus.add(MainMenu(Constants.Menu.ATTRACTIVE, R.string.menu_attractive, R.drawable.ic_terrain_white_36dp, R.color.cyan_500))
73 | menus.add(MainMenu(Constants.Menu.ACCOMMODATION, R.string.menu_accommodation, R.drawable.ic_local_hotel_white_36dp, R.color.purple_500))
74 | return menus
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/guideapp/utilities/ViewUtil.kt:
--------------------------------------------------------------------------------
1 | package com.guideapp.utilities
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.view.animation.AnimationUtils
6 | import com.guideapp.R
7 |
8 | object ViewUtil {
9 | fun showViewLayout(context: Context, view: View) {
10 | var animation = AnimationUtils.loadAnimation(context, R.anim.abc_slide_out_bottom)
11 | animation.duration = 200
12 | view.startAnimation(animation)
13 | view.visibility = View.GONE
14 |
15 | animation = AnimationUtils.loadAnimation(context, R.anim.abc_slide_in_bottom)
16 | animation.duration = 400
17 | view.startAnimation(animation)
18 | view.visibility = View.VISIBLE
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/gruta.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/gruta.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_apps_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_apps_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_apps_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_apps_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_apps_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_apps_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_apps_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_apps_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_bookmark_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_bookmark_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_bookmark_border_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_bookmark_border_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_bookmark_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_bookmark_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_bookmark_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_bookmark_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_call_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_call_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_directions_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_directions_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_info_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_info_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_language_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_language_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_local_dining_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_local_dining_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_local_dining_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_local_dining_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_local_hotel_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_local_hotel_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_location_on_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_location_on_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_location_on_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_location_on_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_map_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_map_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_public_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_public_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_restart_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_restart_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_terrain_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-hdpi/ic_terrain_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_apps_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_apps_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_apps_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_apps_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_apps_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_apps_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_apps_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_apps_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_bookmark_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_bookmark_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_bookmark_border_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_bookmark_border_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_bookmark_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_bookmark_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_bookmark_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_bookmark_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_call_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_call_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_directions_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_directions_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_info_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_info_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_language_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_language_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_local_dining_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_local_dining_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_local_dining_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_local_dining_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_local_hotel_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_local_hotel_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_location_on_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_location_on_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_location_on_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_location_on_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_map_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_map_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_public_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_public_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_restart_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_restart_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_terrain_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-mdpi/ic_terrain_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/appwidget_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-nodpi/appwidget_preview.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_apps_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_apps_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_apps_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_apps_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_apps_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_apps_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_bookmark_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_bookmark_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_bookmark_border_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_bookmark_border_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_bookmark_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_bookmark_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_bookmark_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_bookmark_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_call_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_call_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_directions_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_directions_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_info_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_info_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_language_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_language_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_local_dining_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_local_dining_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_local_dining_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_local_dining_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_local_hotel_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_local_hotel_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_location_on_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_location_on_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_location_on_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_location_on_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_map_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_map_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_public_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_public_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_restart_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_restart_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_terrain_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xhdpi/ic_terrain_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_apps_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_apps_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_apps_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_apps_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_apps_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_apps_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_bookmark_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_bookmark_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_bookmark_border_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_bookmark_border_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_bookmark_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_bookmark_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_bookmark_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_bookmark_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_call_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_call_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_directions_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_directions_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_info_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_info_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_language_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_language_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_local_dining_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_local_dining_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_local_dining_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_local_dining_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_local_hotel_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_local_hotel_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_location_on_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_location_on_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_location_on_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_location_on_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_map_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_map_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_public_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_public_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_restart_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_restart_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_terrain_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxhdpi/ic_terrain_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_apps_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_apps_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_apps_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_apps_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_apps_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_apps_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_bookmark_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_bookmark_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_bookmark_border_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_bookmark_border_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_bookmark_grey_400_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_bookmark_grey_400_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_bookmark_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_bookmark_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_call_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_call_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_directions_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_directions_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_info_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_info_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_language_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_language_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_local_dining_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_local_dining_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_local_hotel_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_local_hotel_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_location_on_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_location_on_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_map_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_map_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_place_dining_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_place_dining_48dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_place_hotel_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_place_hotel_48dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_place_terrain_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_place_terrain_48dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_public_grey_72_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_public_grey_72_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_terrain_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/drawable-xxxhdpi/ic_terrain_white_36dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/action_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/action_background_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_local.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
19 |
20 |
21 |
26 |
27 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_map.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_favorite.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_local.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_map.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
12 |
19 |
20 |
30 |
31 |
42 |
43 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_menu.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_local_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
34 |
35 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_local_favorite.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
23 |
24 |
34 |
35 |
47 |
48 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_local_map.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
21 |
22 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
26 |
27 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toolbar_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
25 |
26 |
34 |
35 |
36 |
41 |
42 |
49 |
50 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_detail_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
24 |
25 |
35 |
36 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_detail.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/transition-v21/details_window_enter_transition.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/transition-v21/details_window_return_transition.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #000000
5 |
6 | #15FFFFFF
7 |
8 | #FFFFFF
9 | #bdbdbd
10 | #f5f5f5
11 |
12 | #212121
13 | #727272
14 | #4CAF50
15 |
16 |
17 | #F5F5F5
18 | #E0E0E0
19 | #E0E0E0
20 |
21 | #FFFFFF
22 |
23 | #55000000
24 | #00000000
25 |
26 | #536DFE
27 | #EEEEEE
28 |
29 | #4CAF50
30 | #2196F3
31 | #9C27B0
32 | #00BCD4
33 | #78909C
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 4dp
6 | 2dp
7 |
8 | 32dp
9 |
10 | 16dp
11 | 16dp
12 |
13 | 4dp
14 | 250dp
15 |
16 | 8dp
17 | 250dp
18 | 180dp
19 | 220dp
20 | @dimen/widget_detail_default_height
21 |
22 | 1dp
23 | 200dp
24 | 0.5dp
25 | 1.5dp
26 |
27 |
28 |
29 | 2dp
30 | 2dp
31 | 50dp
32 | 36dp
33 | 50dp
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Delfinópolis (Brasil)
3 |
4 | Delfinópolis
5 | TN_DetailIcon
6 | ca-app-pub-3940256099942544/6300978111
7 | com.guideapp
8 | loc-status
9 |
10 | Nenhuma informação disponível
11 | Verifique sua conexão e tente novamente
12 | Tivemos um problema ao\ncarregar os dados
13 | Tentar novamente
14 | Você ainda não salvou nenhum local em seus favoritos
15 |
16 |
17 |
18 | Lugares no mapa
19 | Alimentação
20 | Atrativos
21 | hospedagem
22 |
23 |
24 |
25 | Local salvo em favoritos
26 | Local removido em favoritos
27 | Compartilhar local
28 | Local: %1$s\nEndereço: %2$s\nTipo: %3$s\n\n%4$s
29 | Ir
30 | Ligar
31 | WebSite
32 |
33 |
34 |
35 | Meus lugares
36 | Você ainda não salvou nenhum local em seus favoritos
37 | Meus lugares
38 |
39 |
40 |
41 | Imagem do local
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/local_favorite_widget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/backend/build.gradle:
--------------------------------------------------------------------------------
1 | // If you would like more information on the gradle-appengine-plugin please refer to the github page
2 | // https://github.com/GoogleCloudPlatform/gradle-appengine-plugin
3 |
4 | buildscript {
5 | repositories {
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.google.appengine:gradle-appengine-plugin:1.9.50'
10 | }
11 | }
12 |
13 | repositories {
14 | jcenter();
15 | }
16 |
17 | apply plugin: 'java'
18 | apply plugin: 'war'
19 | apply plugin: 'appengine'
20 |
21 | //apply from: '../config/quality-backend.gradle'
22 |
23 | sourceCompatibility = JavaVersion.VERSION_1_7
24 | targetCompatibility = JavaVersion.VERSION_1_7
25 |
26 | dependencies {
27 | appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.50'
28 | compile 'com.google.appengine:appengine-endpoints:1.9.50'
29 |
30 | compile 'com.google.appengine:appengine-endpoints-deps:1.9.50'
31 | compile 'javax.servlet:servlet-api:2.5'
32 |
33 | compile 'com.googlecode.objectify:objectify:5.1.10'
34 | }
35 |
36 | appengine {
37 | downloadSdk = true
38 | appcfg {
39 | oauth2 = true
40 | }
41 | endpoints {
42 | getClientLibsOnBuild = true
43 | getDiscoveryDocsOnBuild = true
44 | }
45 | }
46 |
47 | task grunt(dependsOn: assemble) {
48 | exec({
49 | commandLine = ["ls"]
50 | workingDir = "./src/main/web-angular/"
51 | })
52 | }
53 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/category/CategoryDAO.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.category;
2 |
3 | import com.guideapp.backend.dao.generic.IGenericDAO;
4 | import com.guideapp.backend.entity.Category;
5 |
6 | public interface CategoryDAO extends IGenericDAO {
7 | }
8 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/category/CategoryDAOImpl.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.category;
2 |
3 | import com.guideapp.backend.dao.generic.ObjectifyGenericDAO;
4 | import com.guideapp.backend.entity.Category;
5 |
6 | public class CategoryDAOImpl extends ObjectifyGenericDAO implements CategoryDAO {
7 | }
8 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/city/CityDAO.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.city;
2 |
3 | import com.guideapp.backend.dao.generic.IGenericDAO;
4 | import com.guideapp.backend.entity.City;
5 |
6 | public interface CityDAO extends IGenericDAO {
7 | }
8 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/city/CityDAOImpl.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.city;
2 |
3 | import com.guideapp.backend.dao.generic.ObjectifyGenericDAO;
4 | import com.guideapp.backend.entity.City;
5 |
6 | public class CityDAOImpl extends ObjectifyGenericDAO implements CityDAO {
7 | }
8 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/generic/IGenericDAO.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.generic;
2 |
3 | import com.googlecode.objectify.Key;
4 |
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | public interface IGenericDAO {
9 |
10 | Key save(T entity);
11 |
12 | void insert(T entity);
13 |
14 | void delete(T entity);
15 |
16 | void delete(Iterable> entities);
17 |
18 | void update(T entity);
19 |
20 | List listAll();
21 |
22 | T getByProperty(String propName, Object propValue);
23 |
24 | T getById(Long id);
25 |
26 | T getByKey(Long id);
27 |
28 | List listByProperty(String propName, Object propValue);
29 |
30 | List listByProperties(Map filters);
31 | }
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/local/LocalDAO.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.local;
2 |
3 | import com.guideapp.backend.dao.generic.IGenericDAO;
4 | import com.guideapp.backend.entity.Local;
5 |
6 | import java.util.List;
7 |
8 | public interface LocalDAO extends IGenericDAO {
9 | List listByFilters(Long idCity, Long idCategory, Long[] subCategories);
10 | }
11 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/local/LocalDAOImpl.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.local;
2 |
3 | import com.google.appengine.api.datastore.Query;
4 | import com.guideapp.backend.dao.generic.ObjectifyGenericDAO;
5 | import com.guideapp.backend.entity.Local;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Collection;
9 | import java.util.List;
10 |
11 | import static com.guideapp.backend.util.OfyService.ofy;
12 |
13 | public class LocalDAOImpl extends ObjectifyGenericDAO implements LocalDAO {
14 |
15 | @Override
16 | public List listByFilters(Long idCity, Long idCategory, Long[] subCategories) {
17 | if (idCity == null) {
18 | return null;
19 | }
20 |
21 | if (idCategory != null) {
22 | com.googlecode.objectify.cmd.Query query = ofy().load().type(mClazz);
23 | Collection filtersAnd = new ArrayList<>();
24 | Collection filtersOr = new ArrayList<>();
25 |
26 | filtersAnd.add(new Query.FilterPredicate(
27 | "idCity",
28 | Query.FilterOperator.EQUAL,
29 | idCity));
30 |
31 | filtersAnd.add(new Query.FilterPredicate(
32 | "idCategories",
33 | Query.FilterOperator.EQUAL,
34 | idCategory));
35 |
36 | if (subCategories != null && subCategories.length > 0) {
37 | int size = subCategories.length;
38 |
39 | if (size == 1) {
40 | filtersAnd.add(new Query.FilterPredicate(
41 | "idSubCategories",
42 | Query.FilterOperator.EQUAL,
43 | subCategories[0]));
44 | } else {
45 | for (Long subCategory : subCategories) {
46 | filtersOr.add(new Query.FilterPredicate(
47 | "idSubCategories",
48 | Query.FilterOperator.EQUAL,
49 | subCategory));
50 | }
51 | }
52 | }
53 | Query.Filter filterAnd = Query.CompositeFilterOperator.and(filtersAnd);
54 |
55 |
56 | if (filtersOr.size() > 0) {
57 | Query.Filter filterOr = Query.CompositeFilterOperator.or(filtersOr);
58 |
59 | filterAnd = Query.CompositeFilterOperator.and(filterAnd, filterOr);
60 | }
61 |
62 |
63 | return query.filter(filterAnd).list();
64 | }
65 |
66 | return listByProperty("idCity", idCity);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/subcategory/SubCategoryDAO.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.subcategory;
2 |
3 | import com.guideapp.backend.dao.generic.IGenericDAO;
4 | import com.guideapp.backend.entity.SubCategory;
5 |
6 | public interface SubCategoryDAO extends IGenericDAO {
7 | }
8 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/dao/subcategory/SubCategoryDAOImpl.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.dao.subcategory;
2 |
3 | import com.guideapp.backend.dao.generic.ObjectifyGenericDAO;
4 | import com.guideapp.backend.entity.SubCategory;
5 |
6 | public class SubCategoryDAOImpl extends ObjectifyGenericDAO implements SubCategoryDAO {
7 | }
8 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/entity/Category.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.entity;
2 |
3 | import com.googlecode.objectify.annotation.Entity;
4 | import com.googlecode.objectify.annotation.Id;
5 | import com.guideapp.backend.util.StringUtil;
6 |
7 | @Entity
8 | public class Category {
9 | @Id
10 | private Long id;
11 | private String description;
12 |
13 | private long timestamp;
14 |
15 | public Long getId() {
16 | return id;
17 | }
18 |
19 | public void setId(Long id) {
20 | this.id = id;
21 | }
22 |
23 | public String getDescription() {
24 | return description;
25 | }
26 |
27 | public void setDescription(String description) {
28 | this.description = StringUtil.trim(description);
29 | }
30 |
31 | public long getTimestamp() {
32 | return timestamp;
33 | }
34 |
35 | public void setTimestamp(long timestamp) {
36 | this.timestamp = timestamp;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/entity/City.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.entity;
2 |
3 | import com.googlecode.objectify.annotation.Entity;
4 | import com.googlecode.objectify.annotation.Id;
5 | import com.guideapp.backend.util.StringUtil;
6 |
7 | @Entity
8 | public class City {
9 |
10 | @Id
11 | private Long id;
12 | private String name;
13 | private String uf;
14 | private double latitude;
15 | private double longitude;
16 |
17 | private long timestamp;
18 |
19 | public Long getId() {
20 | return id;
21 | }
22 |
23 | public void setId(Long id) {
24 | this.id = id;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public void setName(String name) {
32 | this.name = StringUtil.trim(name);
33 | }
34 |
35 | public String getUf() {
36 | return uf;
37 | }
38 |
39 | public void setUf(String uf) {
40 | this.uf = StringUtil.trim(uf);
41 | }
42 |
43 | public long getTimestamp() {
44 | return timestamp;
45 | }
46 |
47 | public void setTimestamp(long timestamp) {
48 | this.timestamp = timestamp;
49 | }
50 |
51 | public double getLatitude() {
52 | return latitude;
53 | }
54 |
55 | public void setLatitude(double latitude) {
56 | this.latitude = latitude;
57 | }
58 |
59 | public double getLongitude() {
60 | return longitude;
61 | }
62 |
63 | public void setLongitude(double longitude) {
64 | this.longitude = longitude;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/entity/SubCategory.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.entity;
2 |
3 | import com.googlecode.objectify.annotation.Entity;
4 | import com.googlecode.objectify.annotation.Id;
5 | import com.googlecode.objectify.annotation.Index;
6 | import com.guideapp.backend.util.StringUtil;
7 |
8 | import java.io.Serializable;
9 |
10 | @Entity
11 | public class SubCategory implements Serializable {
12 |
13 | @Id
14 | private Long id;
15 | private String description;
16 |
17 | @Index
18 | private Long idCategory;
19 |
20 | private long timestamp;
21 |
22 | public Long getId() {
23 | return id;
24 | }
25 |
26 | public void setId(Long id) {
27 | this.id = id;
28 | }
29 |
30 | public String getDescription() {
31 | return description;
32 | }
33 |
34 | public void setDescription(String description) {
35 | this.description = StringUtil.trim(description);
36 | }
37 |
38 | public Long getIdCategory() {
39 | return idCategory;
40 | }
41 |
42 | public void setIdCategory(Long idCategory) {
43 | this.idCategory = idCategory;
44 | }
45 |
46 | public long getTimestamp() {
47 | return timestamp;
48 | }
49 |
50 | public void setTimestamp(long timestamp) {
51 | this.timestamp = timestamp;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/service/category/CategoryService.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.service.category;
2 |
3 | import com.google.api.server.spi.response.ConflictException;
4 | import com.google.api.server.spi.response.NotFoundException;
5 | import com.guideapp.backend.entity.Category;
6 |
7 | import java.util.List;
8 |
9 | public interface CategoryService {
10 | /**
11 | * Returns a Category list
12 | */
13 | List list();
14 |
15 | /**
16 | * Returns a Category list by filters
17 | */
18 | List list(String search);
19 |
20 | /**
21 | * Returns a Category object with the given id..
22 | */
23 | Category getById(Long id) throws NotFoundException;
24 |
25 | /**
26 | * Creates a Category object
27 | */
28 | void insert(Category category) throws ConflictException;
29 |
30 | /**
31 | * Updates a City object
32 | */
33 | void update(Category category) throws ConflictException, NotFoundException;
34 |
35 | /**
36 | * Removes a Category object
37 | */
38 | void remove(Long id) throws NotFoundException;
39 | }
40 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/service/category/CategoryServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.service.category;
2 |
3 | import com.google.api.server.spi.response.ConflictException;
4 | import com.google.api.server.spi.response.NotFoundException;
5 | import com.guideapp.backend.dao.category.CategoryDAO;
6 | import com.guideapp.backend.dao.category.CategoryDAOImpl;
7 | import com.guideapp.backend.entity.Category;
8 | import com.guideapp.backend.util.ValidationUtil;
9 |
10 | import java.util.Date;
11 | import java.util.List;
12 |
13 | public class CategoryServiceImpl implements CategoryService {
14 | private final CategoryDAO mCategoryDAO;
15 |
16 | public CategoryServiceImpl() {
17 | this.mCategoryDAO = new CategoryDAOImpl();
18 | }
19 |
20 | @Override
21 | public List list() {
22 | return mCategoryDAO.listAll();
23 | }
24 |
25 | @Override
26 | public List list(String search) {
27 | return mCategoryDAO.listByProperty("name", search);
28 | }
29 |
30 | @Override
31 | public Category getById(Long id) throws NotFoundException {
32 | Category category = mCategoryDAO.getByKey(id);
33 |
34 | if (category == null) {
35 | throw new NotFoundException("Category not found");
36 | }
37 |
38 | return category;
39 | }
40 |
41 | @Override
42 | public void insert(Category category) throws ConflictException {
43 |
44 | if (category == null) {
45 | throw new ConflictException("Categoria não informada.");
46 | }
47 |
48 | if (ValidationUtil.nullOrEmpty(category.getDescription())) {
49 | throw new ConflictException("Descrição não informada.");
50 | }
51 |
52 | category.setTimestamp(new Date().getTime());
53 | mCategoryDAO.insert(category);
54 | }
55 |
56 | @Override
57 | public void update(Category category) throws ConflictException, NotFoundException {
58 | if (category == null) {
59 | throw new ConflictException("Categoria não informada.");
60 | }
61 |
62 | if (ValidationUtil.nullOrEmpty(category.getId())) {
63 | throw new ConflictException("Id não informado.");
64 | }
65 |
66 | if (ValidationUtil.nullOrEmpty(category.getDescription())) {
67 | throw new ConflictException("Descrição não informada.");
68 | }
69 |
70 | Category c = mCategoryDAO.getByKey(category.getId());
71 |
72 | if (c == null) {
73 | throw new NotFoundException("Categoria não encontrada.");
74 | }
75 |
76 | category.setTimestamp(new Date().getTime());
77 | mCategoryDAO.insert(category);
78 | }
79 |
80 | @Override
81 | public void remove(Long id) throws NotFoundException {
82 | Category city = mCategoryDAO.getByKey(id);
83 |
84 | if (city == null) {
85 | throw new NotFoundException("Categoria não encontrada.");
86 | }
87 |
88 | mCategoryDAO.delete(city);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/service/city/CityService.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.service.city;
2 |
3 | import com.google.api.server.spi.response.ConflictException;
4 | import com.google.api.server.spi.response.NotFoundException;
5 | import com.guideapp.backend.entity.City;
6 |
7 | import java.util.List;
8 |
9 | public interface CityService {
10 |
11 | /**
12 | * Returns a cities list
13 | */
14 | List list();
15 |
16 | /**
17 | * Returns a cities list by filters
18 | */
19 | List list(String search);
20 |
21 | /**
22 | * Returns a City object with the given id..
23 | */
24 | City getById(Long id) throws NotFoundException;
25 |
26 |
27 | /**
28 | * Creates a City object
29 | */
30 | void insert(City city) throws ConflictException;
31 |
32 |
33 | /**
34 | * Updates a City object
35 | */
36 | void update(City city) throws ConflictException, NotFoundException;
37 |
38 |
39 | /**
40 | * Removes a City object
41 | */
42 | void remove(Long id) throws NotFoundException;
43 | }
44 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/service/city/CityServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.service.city;
2 |
3 | import com.google.api.server.spi.response.ConflictException;
4 | import com.google.api.server.spi.response.NotFoundException;
5 | import com.guideapp.backend.dao.city.CityDAO;
6 | import com.guideapp.backend.dao.city.CityDAOImpl;
7 | import com.guideapp.backend.entity.City;
8 | import com.guideapp.backend.util.ValidationUtil;
9 |
10 | import java.util.Date;
11 | import java.util.List;
12 |
13 | public class CityServiceImpl implements CityService {
14 | private final CityDAO mCityDAO;
15 |
16 | public CityServiceImpl() {
17 | this.mCityDAO = new CityDAOImpl();
18 | }
19 |
20 | @Override
21 | public List list() {
22 | return mCityDAO.listAll();
23 | }
24 |
25 | @Override
26 | public List list(String search) {
27 | return mCityDAO.listByProperty("name", search);
28 | }
29 |
30 | @Override
31 | public City getById(Long id) throws NotFoundException {
32 | City city = mCityDAO.getByKey(id);
33 |
34 | if (city == null) {
35 | throw new NotFoundException("City not found");
36 | }
37 |
38 | return city;
39 | }
40 |
41 | @Override
42 | public void insert(City city) throws ConflictException {
43 | if (city == null) {
44 | throw new ConflictException("Cidade não informada.");
45 | }
46 |
47 | if (ValidationUtil.nullOrEmpty(city.getName())) {
48 | throw new ConflictException("Nome da cidade não informado.");
49 | }
50 |
51 | if (ValidationUtil.nullOrEmpty(city.getUf())) {
52 | throw new ConflictException("Estado não informado.");
53 | }
54 |
55 | city.setTimestamp(new Date().getTime());
56 | mCityDAO.insert(city);
57 | }
58 |
59 | @Override
60 | public void update(City city) throws ConflictException, NotFoundException {
61 |
62 | if (city == null) {
63 | throw new ConflictException("Cidade não informada.");
64 | }
65 |
66 | if (ValidationUtil.nullOrEmpty(city.getName())) {
67 | throw new ConflictException("Nome da cidade não informado.");
68 | }
69 |
70 | if (ValidationUtil.nullOrEmpty(city.getUf())) {
71 | throw new ConflictException("Estado não informado.");
72 | }
73 |
74 | if (ValidationUtil.nullOrEmpty(city.getId())) {
75 | throw new ConflictException("Id não informado.");
76 | }
77 |
78 | City c = mCityDAO.getByKey(city.getId());
79 |
80 | if (c == null) {
81 | throw new NotFoundException("Cidade não encontrada.");
82 | }
83 |
84 | city.setTimestamp(new Date().getTime());
85 | mCityDAO.insert(city);
86 | }
87 |
88 | @Override
89 | public void remove(Long id) throws NotFoundException {
90 | City city = mCityDAO.getByKey(id);
91 |
92 | if (city == null) {
93 | throw new NotFoundException("Cidade não encontrada.");
94 | }
95 |
96 | mCityDAO.delete(city);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/service/local/LocalService.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.service.local;
2 |
3 | import com.google.api.server.spi.response.ConflictException;
4 | import com.google.api.server.spi.response.NotFoundException;
5 | import com.guideapp.backend.entity.Local;
6 |
7 | import java.util.List;
8 |
9 | public interface LocalService {
10 | /**
11 | * Returns a locals list by filters
12 | */
13 | List list(Long idCity, Long idCategory, Long[] subCategories) throws ConflictException;
14 |
15 | /**
16 | * Returns a locals list by filters
17 | */
18 | List list(String search);
19 |
20 | /**
21 | * Returns a Local object with the given id.
22 | */
23 | Local getById(Long id) throws NotFoundException;
24 |
25 | /**
26 | * Creates a Local object
27 | */
28 | void insert(Local local) throws ConflictException;
29 |
30 | /**
31 | * Updates a Local object
32 | */
33 | void update(Local local) throws ConflictException, NotFoundException;
34 |
35 | /**
36 | * Removes a Local object
37 | */
38 | void remove(Long id) throws NotFoundException;
39 | }
40 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/service/subcategory/SubCategoryService.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.service.subcategory;
2 |
3 | import com.google.api.server.spi.response.ConflictException;
4 | import com.google.api.server.spi.response.NotFoundException;
5 | import com.guideapp.backend.entity.SubCategory;
6 |
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | public interface SubCategoryService {
11 | /**
12 | * Returns a sub-categories list
13 | */
14 | List list();
15 |
16 | /**
17 | * Returns a sub-categories list by Category key
18 | */
19 | List list(Long idCategory);
20 |
21 | /**
22 | * Returns a SubCategory object with the given id..
23 | */
24 | SubCategory getById(Long id) throws NotFoundException;
25 |
26 | /**
27 | * Creates a SubCategory object
28 | */
29 | void insert(SubCategory subCategory) throws ConflictException;
30 |
31 | /**
32 | * Updates a SubCategory object
33 | */
34 | void update(SubCategory subCategory) throws ConflictException, NotFoundException;
35 |
36 | /**
37 | * Removes a SubCategory object
38 | */
39 | void remove(Long id) throws NotFoundException;
40 |
41 | /**
42 | * Get map representing the sub category list
43 | */
44 | Map getMap();
45 | }
46 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/util/Constants.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.util;
2 |
3 | public final class Constants {
4 | public static final String WEB_CLIENT_ID = "904382967622-sl60lsln4f5fmnqac53n2medldl6nt40.apps.googleusercontent.com";
5 | public static final String ANDROID_CLIENT_ID = "2-android-apps.googleusercontent.com";
6 | public static final String IOS_CLIENT_ID = "3-ios-apps.googleusercontent.com";
7 | public static final String ANDROID_AUDIENCE = WEB_CLIENT_ID;
8 | public static final String EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email";
9 | public static final String AUTHORIZATION_REQUIRED = "Authorization required";
10 |
11 | private Constants() {
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/util/MemcacheUtil.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.util;
2 |
3 | import com.google.appengine.api.memcache.ErrorHandlers;
4 | import com.google.appengine.api.memcache.MemcacheService;
5 | import com.google.appengine.api.memcache.MemcacheServiceFactory;
6 |
7 | import java.util.logging.Level;
8 |
9 | public class MemcacheUtil {
10 | public static MemcacheService getMemcacheService(){
11 | MemcacheService syncCache = MemcacheServiceFactory.getMemcacheService();
12 | syncCache.setErrorHandler(ErrorHandlers.getConsistentLogAndContinue(Level.INFO));
13 |
14 | return syncCache;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/util/OfyService.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.util;
2 |
3 | import com.googlecode.objectify.Objectify;
4 | import com.googlecode.objectify.ObjectifyFactory;
5 | import com.googlecode.objectify.ObjectifyService;
6 | import com.guideapp.backend.entity.Category;
7 | import com.guideapp.backend.entity.City;
8 | import com.guideapp.backend.entity.Local;
9 | import com.guideapp.backend.entity.SubCategory;
10 |
11 | public final class OfyService {
12 | private OfyService() {
13 | }
14 |
15 | static {
16 | ObjectifyService.register(SubCategory.class);
17 | ObjectifyService.register(Category.class);
18 | ObjectifyService.register(City.class);
19 | ObjectifyService.register(Local.class);
20 | }
21 |
22 | public static Objectify ofy() {
23 | return ObjectifyService.ofy();
24 | }
25 |
26 | public static ObjectifyFactory factory() {
27 | return ObjectifyService.factory();
28 | }
29 | }
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/util/StringUtil.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.util;
2 |
3 | public final class StringUtil {
4 | private StringUtil() {
5 | }
6 |
7 | public static String trim(String s) {
8 | if (s == null) {
9 | return "";
10 | }
11 |
12 | return s.trim();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/guideapp/backend/util/ValidationUtil.java:
--------------------------------------------------------------------------------
1 | package com.guideapp.backend.util;
2 |
3 | import java.util.List;
4 |
5 | public final class ValidationUtil {
6 |
7 | private ValidationUtil() {
8 | }
9 |
10 | /**
11 | * Check if String is null or empty
12 | */
13 | public static boolean nullOrEmpty(String s) {
14 | return s == null || s.isEmpty();
15 | }
16 |
17 | /**
18 | * Check if Long is null or zero
19 | */
20 | public static boolean nullOrEmpty(Long s) {
21 | return s == null || s == 0;
22 | }
23 |
24 | /**
25 | * Check if double is zero
26 | */
27 | public static boolean nullOrEmpty(double s) {
28 | return s == 0;
29 | }
30 |
31 | /**
32 | * Check if List is null or empty
33 | */
34 | public static boolean nullOrEmpty(List s) {
35 | return s == null || s.isEmpty();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
4 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 |
10 | # Change these settings to your own preference
11 | indent_style = space
12 | indent_size = 2
13 |
14 | # We recommend you to keep these unchanged
15 | end_of_line = lf
16 | charset = utf-8
17 | trim_trailing_whitespace = true
18 | insert_final_newline = true
19 |
20 | [*.md]
21 | trim_trailing_whitespace = false
22 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
--------------------------------------------------------------------------------
/backend/src/main/web-angular/.jscsrc:
--------------------------------------------------------------------------------
1 | {
2 | "requireCamelCaseOrUpperCaseIdentifiers": null,
3 | "requireCapitalizedConstructors": true,
4 | "requireParenthesesAroundIIFE": true,
5 | "validateQuoteMarks": "'"
6 | }
7 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "browser": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "esnext": true,
7 | "latedef": true,
8 | "noarg": true,
9 | "node": true,
10 | "strict": true,
11 | "undef": true,
12 | "unused": true,
13 | "globals": {
14 | "angular": false
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-karma": {
3 | "base-path": "../",
4 | "frameworks": "jasmine",
5 | "browsers": "PhantomJS",
6 | "app-files": "app/scripts/**/*.js",
7 | "files-comments": "bower:js,endbower",
8 | "bower-components-path": "bower_components",
9 | "test-files": "test/mock/**/*.js,test/spec/**/*.js"
10 | }
11 | }
--------------------------------------------------------------------------------
/backend/src/main/web-angular/Archive.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/Archive.zip
--------------------------------------------------------------------------------
/backend/src/main/web-angular/README.md:
--------------------------------------------------------------------------------
1 | ## Web Angular
2 |
3 | To get started:
4 |
5 |
6 | Clone the repository and its submodules:
7 |
8 | ```bash
9 | git clone https://github.com/thaleslima/GuideApp.git
10 | cd backend/src/main/web-angular/
11 | ```
12 |
13 |
14 | Install all modules and needed tools
15 |
16 | ```bash
17 | npm install -g npm
18 | npm install -g yo
19 | npm install -g grunt
20 | npm install -g grunt-cli
21 | npm install -g bower
22 | npm install
23 | bower install
24 | ```
25 |
26 |
27 | Distribute and build
28 | ```bash
29 | grunt
30 | ```
31 |
32 |
33 | Quick run
34 | ```bash
35 | grunt serve
36 | ```
37 |
38 |
39 | Add route
40 | ```bash
41 | yo angular:route myroute
42 | ```
43 |
44 |
45 | Add components bower
46 | ```bash
47 | bower install bootstrap
48 | ```
49 |
50 |
51 | Testing
52 | ```bash
53 | grunt test
54 | ```
55 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/favicon.ico
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/image/ring-alt.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/image/ring-alt.gif
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/image/yeoman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/image/yeoman.png
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org
2 |
3 | User-agent: *
4 | Disallow:
5 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/scripts/controllers/about.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * @ngdoc function
5 | * @name guideAppApp.controller:AboutCtrl
6 | * @description
7 | * # AboutCtrl
8 | * Controller of the guideAppApp
9 | */
10 |
11 | /*global angular */
12 | angular.module('guideAppApp')
13 | .controller('AboutCtrl', function () {
14 | 'use strict';
15 |
16 | this.awesomeThings = [
17 | 'HTML5 Boilerplate',
18 | 'AngularJS',
19 | 'Karma'
20 | ];
21 | });
22 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/scripts/controllers/categories.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * @ngdoc function
5 | * @name guideAppApp.controller:CategoriesCtrl
6 | * @description
7 | * # CategoriesCtrl
8 | * Controller of the guideAppApp
9 | */
10 |
11 | /*jslint devel: true */
12 | /*global angular */
13 | angular.module('guideAppApp')
14 | .controller('CategoriesCtrl', ['$scope', '$location', '$rootScope', '$dataFactory', function ($scope, $location, $rootScope, $dataFactory) {
15 | 'use strict';
16 |
17 | var
18 | getEntitiesSuccess = function (data) {
19 | console.log('success');
20 | console.log(data);
21 | $scope.entities = data.items;
22 | $scope.$apply();
23 | },
24 |
25 | getEntitiesError = function (data) {
26 | console.log('error');
27 | console.log(data);
28 | },
29 |
30 | deleteEntitySuccess = function (data) {
31 | console.log('success');
32 | console.log(data);
33 |
34 | $dataFactory.getCategories(getEntitiesSuccess, getEntitiesError);
35 | },
36 |
37 | deleteEntityError = function (data) {
38 | console.log('error');
39 | console.log(data);
40 | };
41 |
42 |
43 | $scope.init = function () {
44 | $dataFactory.getCategories(getEntitiesSuccess, getEntitiesError);
45 | };
46 |
47 | $scope.deleteEntityById = function (id) {
48 | $dataFactory.removeCategory(id, deleteEntitySuccess, deleteEntityError);
49 | };
50 |
51 | $rootScope.init($scope);
52 |
53 | }]);
54 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/scripts/controllers/cities.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ngdoc function
3 | * @name guideAppApp.controller:CitiesCtrl
4 | * @description
5 | * # CitiesCtrl
6 | * Controller of the guideAppApp
7 | */
8 |
9 | /*jslint devel: true */
10 | /*global angular */
11 | angular.module('guideAppApp')
12 | .controller('CitiesCtrl', ['$scope', '$location', '$rootScope', '$dataFactory', function ($scope, $location, $rootScope, $dataFactory) {
13 | 'use strict';
14 |
15 | var
16 | getEntitiesSuccess = function (data) {
17 | console.log('success');
18 | console.log(data);
19 | $scope.entities = data.items;
20 | $scope.$apply();
21 | },
22 |
23 | getEntitiesError = function (data) {
24 | console.log('error');
25 | console.log(data);
26 | },
27 |
28 | deleteEntitySuccess = function (data) {
29 | console.log('success');
30 | console.log(data);
31 |
32 | $dataFactory.getCities(getEntitiesSuccess, getEntitiesError);
33 | },
34 |
35 | deleteEntityError = function (data) {
36 | console.log('error');
37 | console.log(data);
38 | };
39 |
40 |
41 | $scope.init = function () {
42 | $dataFactory.getCities(getEntitiesSuccess, getEntitiesError);
43 | };
44 |
45 | $scope.deleteEntityById = function (id) {
46 | $dataFactory.removeCity(id, deleteEntitySuccess, deleteEntityError);
47 | };
48 |
49 | $rootScope.init($scope);
50 | }]);
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/scripts/controllers/login.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ngdoc function
3 | * @name guideAppApp.controller:LoginCtrl
4 | * @description
5 | * # LoginCtrl
6 | * Controller of the guideAppApp
7 | */
8 |
9 | /*global angular, $i, removeClass */
10 | angular.module('guideAppApp')
11 | .controller('LoginCtrl', ['$scope', function () {
12 | 'use strict';
13 |
14 | $i('nav-bar').style.display = 'none';
15 | removeClass($i('g-signin-center'), 'hide');
16 |
17 | }]);
18 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/scripts/controllers/main.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * @ngdoc function
5 | * @name guideAppApp.controller:MainCtrl
6 | * @description
7 | * # MainCtrl
8 | * Controller of the guideAppApp
9 | */
10 |
11 | /*jslint devel: true */
12 | /*global angular */
13 | angular.module('guideAppApp')
14 | .controller('MainCtrl', ['$scope', '$location', '$rootScope', '$dataFactory', function ($scope, $location, $rootScope, $dataFactory) {
15 | 'use strict';
16 |
17 | var
18 | getCitiesSuccess = function (data) {
19 | console.log('Success');
20 | $scope.cities = data.items;
21 | console.log(data);
22 | $scope.$apply();
23 | },
24 |
25 | getCitiesError = function (data) {
26 | console.log('error');
27 | console.log(data);
28 |
29 | },
30 |
31 | getEntitiesSuccess = function (data) {
32 | console.log('ok');
33 | console.log(data);
34 |
35 | if (data && data.items) {
36 | var positions = [];
37 | $scope.randomMarkers = [];
38 |
39 | data.items.forEach(function (element, index) {
40 | var p = {
41 | id: index,
42 | latitude: element.latitude,
43 | longitude: element.longitude,
44 | title: 'm'
45 | };
46 |
47 | positions.push(p);
48 | });
49 |
50 | $scope.randomMarkers = positions;
51 | $scope.$apply();
52 | }
53 |
54 | },
55 |
56 | getEntitiesError = function (data) {
57 | console.log('error');
58 | console.log(data);
59 | };
60 |
61 | $scope.map = { center: { latitude: $rootScope.mLatitude, longitude: $rootScope.mLongitude }, zoom: 4 };
62 | $scope.randomMarkers = [];
63 |
64 | $scope.init = function () {
65 | $dataFactory.getCities(getCitiesSuccess, getCitiesError);
66 | };
67 |
68 | $scope.selectCityChange = function () {
69 | console.log($scope.selectCity);
70 | var selectCity = $scope.selectCity,
71 | latitude = selectCity.latitude,
72 | longitude = selectCity.longitude;
73 |
74 | $scope.map = { center: { latitude: latitude, longitude: longitude}, zoom: 14 };
75 | $dataFactory.getLocalsByIdCategory(selectCity.id, null, getEntitiesSuccess, getEntitiesError);
76 | };
77 |
78 | $rootScope.init($scope);
79 |
80 | }]);
81 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/scripts/controllers/sub-categories.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * @ngdoc function
5 | * @name guideAppApp.controller:SubCategoriesCtrl
6 | * @description
7 | * # SubCategoriesCtrl
8 | * Controller of the guideAppApp
9 | */
10 |
11 | /*jslint devel: true */
12 | /*global angular */
13 | angular.module('guideAppApp')
14 | .controller('SubCategoriesCtrl', ['$scope', '$location', '$rootScope', '$dataFactory', function ($scope, $location, $rootScope, $dataFactory) {
15 | 'use strict';
16 |
17 | var
18 | getEntitiesSuccess = function (data) {
19 | console.log('success');
20 | console.log(data);
21 | $scope.entities = data.items;
22 | $scope.$apply();
23 | },
24 |
25 | getEntitiesError = function (data) {
26 | console.log('error');
27 | console.log(data);
28 | },
29 |
30 | deleteEntitySuccess = function (data) {
31 | console.log('success');
32 | console.log(data);
33 |
34 | $dataFactory.getSubCategories(getEntitiesSuccess, getEntitiesError);
35 | },
36 |
37 | deleteEntityError = function (data) {
38 | console.log('error');
39 | console.log(data);
40 | };
41 |
42 |
43 | $scope.init = function () {
44 | $dataFactory.getSubCategories(getEntitiesSuccess, getEntitiesError);
45 | };
46 |
47 | $scope.deleteEntityById = function (id) {
48 | $dataFactory.removeSubCategory(id, deleteEntitySuccess, deleteEntityError);
49 | };
50 |
51 | $rootScope.init($scope);
52 | }]);
53 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/styles/main.css:
--------------------------------------------------------------------------------
1 | .page-main .angular-google-map-container {
2 | position: absolute;
3 | bottom: 0px;
4 | top: 50px;
5 | right: 0px;
6 | left: 0px;
7 | }
8 |
9 | .page-main .filter{
10 | z-index: 100;
11 | padding-left: 15px;
12 | margin-top: 7;
13 | }
14 |
15 | .page-main #page-wrapper {
16 | padding-top: 10px;
17 | }
18 |
19 |
20 | @media (min-width: 768px){
21 | .page-main .angular-google-map-container {
22 | left: 225px;
23 | }
24 |
25 | .page-main #page-wrapper {
26 | padding-left: 130px;
27 | padding-top: 0px;
28 | }
29 |
30 | .page-main .filter{
31 | margin-top: 7px;
32 | }
33 | }
34 |
35 |
36 | .page-cities-new-edit #map-canvas {
37 | width: 100%;
38 | height: 300px;
39 | }
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .page-locais-new-edit #map-canvas {
48 | width:100%;
49 | height:300px;
50 | }
51 |
52 | .page-locais-new-edit .image {
53 | position: relative;
54 | text-align: center;
55 | border: 1px solid #DDD;
56 | background: #FFF;
57 | width: 280px;
58 | min-height: 180px;
59 | padding: 2px;
60 | border-radius: 4px;
61 | cursor: move;
62 | }
63 |
64 | .page-locais-new-edit .image.empty {
65 | background: #f8f8f6;
66 | border: 1px dashed #CCC;
67 | cursor: default;
68 | }
69 |
70 | .page-locais-new-edit .image .glyphicon {
71 | opacity:0.5;
72 | -moz-opacity: 0.65;
73 | filter: alpha(opacity=65);
74 | }
75 |
76 | .page-locais-new-edit .text-upload-file {
77 | font-size: 10px;
78 | display: block;
79 | margin-top: 70px;
80 | }
81 |
82 | .page-locais-new-edit .image-loading{
83 | width: 30px;
84 | height: 30px;
85 | display: inline-block;
86 | position: relative;
87 | margin-top: 70px;
88 | }
89 |
90 | .page-locais-new-edit .ring-alt{
91 | background-image: url('../image/ring-alt.gif');
92 | background-size: 30px 30px;
93 | }
94 |
95 | .g-signin-center{
96 | width: 100%;
97 | position: absolute;
98 | bottom: 160px;
99 | display: inline-flex;
100 | }
101 |
102 |
103 | .g-signin-center .g-signin2{
104 | margin: 0 auto;
105 | }
106 |
107 | .image-user {
108 | width: 20px;
109 | height: 20px;
110 | border-radius: 150px;
111 | -webkit-border-radius: 150px;
112 | -moz-border-radius: 150px;
113 | }
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/views/about.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 | -
13 | Dashboard
14 |
15 | -
16 | Blank Page
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/views/category-new-edit.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
12 | -
13 | Home
14 |
15 |
16 | -
17 | Categorias
18 |
19 |
20 | -
21 | {{page}}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/views/login.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/app/views/login.html
--------------------------------------------------------------------------------
/backend/src/main/web-angular/app/views/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "guide-app",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "angular": "^1.4.0",
6 | "bootstrap": "^3.2.0",
7 | "angular-animate": "^1.4.0",
8 | "angular-aria": "^1.4.0",
9 | "angular-cookies": "^1.4.0",
10 | "angular-messages": "^1.4.0",
11 | "angular-resource": "^1.4.0",
12 | "angular-route": "^1.4.0",
13 | "angular-sanitize": "^1.4.0",
14 | "angular-touch": "^1.4.0",
15 | "angular-google-maps": "^2.3.2",
16 | "components-font-awesome": "^4.5.0"
17 | },
18 | "devDependencies": {
19 | "angular-mocks": "^1.4.0"
20 | },
21 | "appPath": "app",
22 | "moduleName": "guideAppApp",
23 | "overrides": {
24 | "bootstrap": {
25 | "main": [
26 | "less/bootstrap.less",
27 | "dist/css/bootstrap.css",
28 | "dist/js/bootstrap.js"
29 | ]
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/old/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "startbootstrap-sb-admin-2",
3 | "version": "1.0.7",
4 | "homepage": "http://startbootstrap.com/template-overviews/sb-admin-2/",
5 | "authors": [
6 | "David Miller"
7 | ],
8 | "description": "A free, open source, Bootstrap admin theme created by Start Bootstrap",
9 | "keywords": [
10 | "bootstrap",
11 | "theme"
12 | ],
13 | "license": "Apache",
14 | "ignore": [
15 | "**/.*",
16 | "node_modules",
17 | "bower_components",
18 | "test",
19 | "tests",
20 | "pages",
21 | "index.html",
22 | "/js"
23 | ],
24 | "main": [
25 | "dist/css/sb-admin-2.css",
26 | "dist/js/sb-admin-2.js"
27 | ],
28 | "dependencies": {
29 | "bootstrap": "~3.3.6",
30 | "datatables": "~1.10.4",
31 | "datatables-plugins": "~1.0.1",
32 | "flot": "~0.8.3",
33 | "font-awesome": "~4.2.0",
34 | "holderjs": "~2.4.1",
35 | "metisMenu": "~1.1.3",
36 | "morrisjs": "~0.5.1",
37 | "datatables-responsive": "~1.0.3",
38 | "bootstrap-social": "~4.8.0",
39 | "flot.tooltip": "~0.8.4"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/old/dist2/css/cities.css:
--------------------------------------------------------------------------------
1 | #map-canvas {
2 | width:100%;
3 | height:300px;
4 | }
--------------------------------------------------------------------------------
/backend/src/main/web-angular/old/dist2/css/index.css:
--------------------------------------------------------------------------------
1 | #map-canvas {
2 | position: absolute;
3 | bottom: 0px;
4 | top: 60px;
5 | right: 0px;
6 | left: 0px;
7 | z-index: 90;
8 | }
9 |
10 | .container-fluid{
11 | margin-right: 100px;
12 | }
13 |
14 | #page-wrapper {
15 | padding: inherit;
16 | }
17 |
18 | .filter{
19 | z-index: 100;
20 | padding-left: 15px;
21 | margin-top: 7px;
22 | }
23 |
24 |
25 | @media (min-width: 768px){
26 | #map-canvas {
27 | left: 250px;
28 | }
29 |
30 | #page-wrapper {
31 | padding-left: 130px
32 | }
33 | }
34 |
35 | #search-id-city{
36 | box-shadow: rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px;
37 | }
38 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/old/dist2/css/locals.css:
--------------------------------------------------------------------------------
1 | #map-canvas {
2 | width:100%;
3 | height:300px;
4 | }
5 |
6 | .image {
7 | position: relative;
8 | text-align: center;
9 | border: 1px solid #DDD;
10 | background: #FFF;
11 | width: 280px;
12 | min-height: 180px;
13 | padding: 2px;
14 | border-radius: 4px;
15 | cursor: move;
16 | }
17 |
18 | .image.empty {
19 | background: #f8f8f6;
20 | border: 1px dashed #CCC;
21 | cursor: default;
22 | }
23 |
24 | .image .glyphicon {
25 | opacity:0.5;
26 | -moz-opacity: 0.65;
27 | filter: alpha(opacity=65);
28 | }
29 |
30 | .text-upload-file {
31 | font-size: 10px;
32 | display: block;
33 | margin-top: 70px;
34 | }
35 |
36 | .image-loading{
37 | width: 30px;
38 | height: 30px;
39 | display: inline-block;
40 | position: relative;
41 | margin-top: 70px;
42 | }
43 |
44 | .ring-alt{
45 | background-image: url('../image/ring-alt.gif');
46 | background-size: 30px 30px;
47 | }
--------------------------------------------------------------------------------
/backend/src/main/web-angular/old/dist2/image/ring-alt.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/web-angular/old/dist2/image/ring-alt.gif
--------------------------------------------------------------------------------
/backend/src/main/web-angular/old/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SB Admin 2
6 |
9 |
10 |
11 | Go to /pages/index.html
12 |
13 |
14 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/old/pages/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Guia App - Adm
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
Please Sign In
45 |
46 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "guideapp",
3 | "private": true,
4 | "devDependencies": {
5 | "autoprefixer-core": "^5.2.1",
6 | "grunt": "^0.4.5",
7 | "grunt-angular-templates": "^0.5.7",
8 | "grunt-concurrent": "^1.0.0",
9 | "grunt-contrib-clean": "^0.6.0",
10 | "grunt-contrib-concat": "^0.5.0",
11 | "grunt-contrib-connect": "^0.9.0",
12 | "grunt-contrib-copy": "^0.7.0",
13 | "grunt-contrib-cssmin": "^0.12.0",
14 | "grunt-contrib-htmlmin": "^0.4.0",
15 | "grunt-contrib-imagemin": "^1.0.0",
16 | "grunt-contrib-jshint": "^0.11.0",
17 | "grunt-contrib-uglify": "^0.7.0",
18 | "grunt-contrib-watch": "^0.6.1",
19 | "grunt-filerev": "^2.1.2",
20 | "grunt-google-cdn": "^0.4.3",
21 | "grunt-jscs": "^1.8.0",
22 | "grunt-newer": "^1.1.0",
23 | "grunt-ng-annotate": "^0.9.2",
24 | "grunt-postcss": "^0.5.5",
25 | "grunt-svgmin": "^2.0.0",
26 | "grunt-usemin": "^3.0.0",
27 | "grunt-wiredep": "^2.0.0",
28 | "jasmine-core": "^2.4.1",
29 | "jit-grunt": "^0.9.1",
30 | "jshint-stylish": "^1.0.0",
31 | "karma": "^0.13.21",
32 | "karma-jasmine": "^0.3.7",
33 | "karma-phantomjs-launcher": "^1.0.0",
34 | "phantomjs-prebuilt": "^2.1.4",
35 | "time-grunt": "^1.0.0"
36 | },
37 | "engines": {
38 | "node": ">=0.10.0"
39 | },
40 | "scripts": {
41 | "test": "karma start test/karma.conf.js"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "browser": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "esnext": true,
7 | "jasmine": true,
8 | "latedef": true,
9 | "noarg": true,
10 | "node": true,
11 | "strict": true,
12 | "undef": true,
13 | "unused": true,
14 | "globals": {
15 | "angular": false,
16 | "inject": false
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on 2016-02-28
3 |
4 | module.exports = function(config) {
5 | 'use strict';
6 |
7 | config.set({
8 | // enable / disable watching file and executing tests whenever any file changes
9 | autoWatch: true,
10 |
11 | // base path, that will be used to resolve files and exclude
12 | basePath: '../',
13 |
14 | // testing framework to use (jasmine/mocha/qunit/...)
15 | // as well as any additional frameworks (requirejs/chai/sinon/...)
16 | frameworks: [
17 | 'jasmine'
18 | ],
19 |
20 | // list of files / patterns to load in the browser
21 | files: [
22 | // bower:js
23 | 'bower_components/jquery/dist/jquery.js',
24 | 'bower_components/angular/angular.js',
25 | 'bower_components/bootstrap/dist/js/bootstrap.js',
26 | 'bower_components/angular-animate/angular-animate.js',
27 | 'bower_components/angular-aria/angular-aria.js',
28 | 'bower_components/angular-cookies/angular-cookies.js',
29 | 'bower_components/angular-messages/angular-messages.js',
30 | 'bower_components/angular-resource/angular-resource.js',
31 | 'bower_components/angular-route/angular-route.js',
32 | 'bower_components/angular-sanitize/angular-sanitize.js',
33 | 'bower_components/angular-touch/angular-touch.js',
34 | 'bower_components/angular-simple-logger/dist/angular-simple-logger.js',
35 | 'bower_components/lodash/lodash.js',
36 | 'bower_components/angular-google-maps/dist/angular-google-maps.js',
37 | 'bower_components/angular-mocks/angular-mocks.js',
38 | // endbower
39 | 'app/scripts/**/*.js',
40 | 'test/mock/**/*.js',
41 | 'test/spec/**/*.js'
42 | ],
43 |
44 | // list of files / patterns to exclude
45 | exclude: [
46 | ],
47 |
48 | // web server port
49 | port: 8080,
50 |
51 | // Start these browsers, currently available:
52 | // - Chrome
53 | // - ChromeCanary
54 | // - Firefox
55 | // - Opera
56 | // - Safari (only Mac)
57 | // - PhantomJS
58 | // - IE (only Windows)
59 | browsers: [
60 | 'PhantomJS'
61 | ],
62 |
63 | // Which plugins to enable
64 | plugins: [
65 | 'karma-phantomjs-launcher',
66 | 'karma-jasmine'
67 | ],
68 |
69 | // Continuous Integration mode
70 | // if true, it capture browsers, run tests and exit
71 | singleRun: false,
72 |
73 | colors: true,
74 |
75 | // level of logging
76 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
77 | logLevel: config.LOG_INFO,
78 |
79 | // Uncomment the following lines if you are using grunt's server to run the tests
80 | // proxies: {
81 | // '/': 'http://localhost:9000/'
82 | // },
83 | // URL root prevent conflicts with the site root
84 | // urlRoot: '_karma_'
85 | });
86 | };
87 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/about.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: AboutCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var AboutCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | AboutCtrl = $controller('AboutCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(AboutCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/categories.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: CategoriesCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var CategoriesCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | CategoriesCtrl = $controller('CategoriesCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(CategoriesCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/category-new-edit.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: CategoryNewEditCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var CategoryNewEditCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | CategoryNewEditCtrl = $controller('CategoryNewEditCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(CategoryNewEditCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/cities.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: CitiesCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var CitiesCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | CitiesCtrl = $controller('CitiesCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(CitiesCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/citynewedit.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: CityneweditCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var CityneweditCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | CityneweditCtrl = $controller('CityneweditCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(CityneweditCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/local-new-edit.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: LocalNewEditCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var LocalNewEditCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | LocalNewEditCtrl = $controller('LocalNewEditCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(LocalNewEditCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/locals.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: LocalsCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var LocalsCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | LocalsCtrl = $controller('LocalsCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(LocalsCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/login.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: LoginCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var LoginCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | LoginCtrl = $controller('LoginCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(LoginCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: MainCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var MainCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | MainCtrl = $controller('MainCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(MainCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/sub-categories.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: SubCategoriesCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var SubCategoriesCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | SubCategoriesCtrl = $controller('SubCategoriesCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(SubCategoriesCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/web-angular/test/spec/controllers/sub-category-new-edit.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: SubCategoryNewEditCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('guideAppApp'));
7 |
8 | var SubCategoryNewEditCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | SubCategoryNewEditCtrl = $controller('SubCategoryNewEditCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(SubCategoryNewEditCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/backend/src/main/webapp/WEB-INF/appengine-web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | guideapp-br
4 | 1
5 | true
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/backend/src/main/webapp/WEB-INF/logging.properties:
--------------------------------------------------------------------------------
1 | # A default java.util.logging configuration.
2 | # (All App Engine logging is through java.util.logging by default).
3 | #
4 | # To use this configuration, copy it into your application's WEB-INF
5 | # folder and add the following to your appengine-web.xml:
6 | #
7 | #
8 | #
9 | #
10 | #
11 |
12 | # Set the default logging level for all loggers to WARNING
13 | .level = WARNING
14 |
--------------------------------------------------------------------------------
/backend/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SystemServiceServlet
5 | com.google.api.server.spi.SystemServiceServlet
6 |
7 | services
8 | com.guideapp.backend.spi.GuideAppEndpoint
9 |
10 |
11 |
12 | SystemServiceServlet
13 | /_ah/spi/*
14 |
15 |
16 |
17 | index.html
18 |
19 |
20 |
21 | ObjectifyFilter
22 | com.googlecode.objectify.ObjectifyFilter
23 |
24 |
25 | ObjectifyFilter
26 | /*
27 |
28 |
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/favicon.ico
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/backend/src/main/webapp/adm/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/backend/src/main/webapp/adm/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org
2 |
3 | User-agent: *
4 | Disallow:
5 |
--------------------------------------------------------------------------------
/backend/src/main/webapp/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Guide App
6 |
9 |
10 |
11 | Go to /adm/
12 |
13 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.1.2-4'
5 | repositories {
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.0.0-alpha3'
10 | classpath 'com.google.gms:google-services:3.0.0'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | ext {
22 | minSdkVersion = 18
23 | targetSdkVersion = 25
24 | compileSdkVersion = 25
25 | buildToolsVersion = '25.0.2'
26 |
27 | // App dependencies
28 | supportLibraryVersion = '25.3.1'
29 | glideVersion = '3.7.0'
30 | playServicesVersion = '10.2.6'
31 | imageZoomVersion = '1.0.5'
32 | retrofitVersion = '2.0.1'
33 | loggingInterceptorVersion = '3.1.2'
34 | guavaVersion = '20.0'
35 | jobdispatcherVersion = '0.5.0'
36 | stethoVersion = '1.4.2'
37 | multidexVersion = '1.0.1'
38 | firebaseVersion = '10.0.1'
39 | }
40 |
--------------------------------------------------------------------------------
/config/quality/findbugs/android-exclude-filter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/config/quality/pmd/pmd-ruleset.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | Custom ruleset for ribot Android application
8 |
9 | .*/R.java
10 | .*/gen/.*
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/config/quality/quality.gradle:
--------------------------------------------------------------------------------
1 | /**
2 | * Set up Checkstyle, Findbugs and PMD to perform extensive code analysis.
3 | *
4 | * Gradle tasks added:
5 | * - checkstyle
6 | * - findbugs
7 | * - pmd
8 | *
9 | * The three tasks above are added as dependencies of the check task so running check will
10 | * run all of them.
11 | */
12 |
13 | apply plugin: 'checkstyle'
14 | apply plugin: 'findbugs'
15 | apply plugin: 'pmd'
16 |
17 | dependencies {
18 | checkstyle 'com.puppycrawl.tools:checkstyle:6.5'
19 | }
20 |
21 | def qualityConfigDir = "$project.rootDir/config/quality";
22 | def reportsDir = "$project.buildDir/reports"
23 |
24 | check.dependsOn 'checkstyle', 'findbugs', 'pmd'
25 |
26 | task checkstyle(type: Checkstyle, group: 'Verification', description: 'Runs code style checks') {
27 | configFile file("$qualityConfigDir/checkstyle/checkstyle-config.xml")
28 | source 'src'
29 | include '**/*.java'
30 | ignoreFailures = true
31 |
32 | reports {
33 | xml.enabled = true
34 | xml {
35 | destination "$reportsDir/checkstyle/checkstyle.xml"
36 | }
37 | }
38 |
39 | classpath = files( )
40 | }
41 |
42 | task findbugs(type: FindBugs,
43 | group: 'Verification',
44 | description: 'Inspect java bytecode for bugs',
45 | dependsOn: assemble) {
46 |
47 | ignoreFailures = true
48 | effort = "max"
49 | reportLevel = "high"
50 | excludeFilter = new File("$qualityConfigDir/findbugs/android-exclude-filter.xml")
51 | classes = files("$project.rootDir/app/build/intermediates/classes")
52 |
53 | source 'src'
54 | include '**/*.java'
55 | exclude '**/gen/**'
56 |
57 | reports {
58 | xml.enabled = true
59 | html.enabled = false
60 | xml {
61 | destination "$reportsDir/findbugs/findbugs.xml"
62 | }
63 | html {
64 | destination "$reportsDir/findbugs/findbugs.html"
65 | }
66 | }
67 |
68 | classpath = files()
69 | }
70 |
71 |
72 | task pmd(type: Pmd, group: 'Verification', description: 'Inspect sourcecode for bugs') {
73 | ruleSetFiles = files("$qualityConfigDir/pmd/pmd-ruleset.xml")
74 | ignoreFailures = true
75 | ruleSets = []
76 |
77 | source 'src'
78 | include '**/*.java'
79 | exclude '**/gen/**'
80 |
81 | reports {
82 | xml.enabled = true
83 | html.enabled = true
84 | xml {
85 | destination "$reportsDir/pmd/pmd.xml"
86 | }
87 | html {
88 | destination "$reportsDir/pmd/pmd.html"
89 | }
90 | }
91 | }
92 |
93 | android {
94 | lintOptions {
95 | checkReleaseBuilds false
96 | abortOnError false
97 | /*xmlReport false
98 | htmlReport true
99 | lintConfig file("${project.rootDir}/config/quality/lint/lint.xml")
100 | htmlOutput file("$project.buildDir/reports/lint/lint-result.html")
101 | xmlOutput file("$project.buildDir/reports/lint/lint-result.xml")*/
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed May 17 21:30:20 BRT 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/images/backend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/images/backend.png
--------------------------------------------------------------------------------
/images/mvp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/images/mvp.png
--------------------------------------------------------------------------------
/images/screenshot_00.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/images/screenshot_00.png
--------------------------------------------------------------------------------
/key/app.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thaleslima/GuideApp/11610228921dd7b0a5606bce1f585e3f0854a177/key/app.jks
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':backend'
2 |
--------------------------------------------------------------------------------