Merge branch 'master' of https://github.com/MikeCodesDotNet/Mobile-Cloud-Workshop
This commit is contained in:
Коммит
d0c2b872c5
|
@ -17,29 +17,36 @@ namespace ContosoMaintenance.WebAPI.Controllers
|
|||
|
||||
public SearchController(IConfiguration configuration)
|
||||
{
|
||||
serviceClient = new SearchServiceClient(configuration["AzureSearch:AzureSearchServiceName"], new SearchCredentials(configuration["AzureSearch:AzureSearchApiKey"]));
|
||||
serviceClient = new SearchServiceClient(configuration["AzureSearch:AzureSearchServiceName"], new SearchCredentials(configuration["AzureSearch:AzureSearchApiKey"]));
|
||||
}
|
||||
|
||||
[Route("/api/search/jobs")]
|
||||
public async Task<List<Job>> Get(string keyword)
|
||||
{
|
||||
var sp = new SearchParameters();
|
||||
var sp = new SuggestParameters();
|
||||
sp.HighlightPreTag = "[";
|
||||
sp.HighlightPostTag = "]";
|
||||
sp.UseFuzzyMatching = true;
|
||||
sp.MinimumCoverage = 50;
|
||||
sp.Top = 100;
|
||||
|
||||
var indexClient = serviceClient.Indexes.GetClient("job-index");
|
||||
|
||||
var response = await indexClient.Documents.SearchAsync<Job>(keyword, sp);
|
||||
var response = await indexClient.Documents.SuggestAsync<Job>(keyword, "suggestions", sp);
|
||||
|
||||
var jobList = new List<Job>();
|
||||
foreach (var document in response.Results)
|
||||
{
|
||||
Job job = new Job
|
||||
var job = new Job
|
||||
{
|
||||
Name = document.Document.Name,
|
||||
Details = document.Document.Details
|
||||
Name = document.Text,
|
||||
Details = document.Document.Details,
|
||||
Status = document.Document.Status,
|
||||
};
|
||||
|
||||
|
||||
jobList.Add(job);
|
||||
}
|
||||
return jobList;
|
||||
return jobList;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ContosoMaintenance.WebAPI.Models
|
||||
{
|
||||
public class GeoPoint
|
||||
{
|
||||
[JsonProperty("longitude")]
|
||||
public double Longitude { get; set; }
|
||||
|
||||
[JsonProperty("latitude")]
|
||||
public double Latitude { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is here as a small hack due to ensure compatibilty between old data in our DB and new data.
|
||||
/// </summary>
|
||||
/// <value>The coordinates.</value>
|
||||
double[] coordinates;
|
||||
[Obsolete("Coordinates is deprecated, please use the Longitude and Latitude properties instead.")]
|
||||
[JsonProperty("coordinates")]
|
||||
public double[] Coordinates
|
||||
{
|
||||
get
|
||||
{
|
||||
if (coordinates == null)
|
||||
return new double[] { Longitude, Latitude };
|
||||
return coordinates;
|
||||
}
|
||||
set
|
||||
{
|
||||
coordinates = value;
|
||||
Latitude = coordinates[0];
|
||||
Longitude = coordinates[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.Azure.Documents.Spatial;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ContosoMaintenance.WebAPI.Models
|
||||
{
|
||||
|
|
|
@ -28,7 +28,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContosoMaintenance.WebAPI",
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContosoMaintenance.Functions", "Backend\Functions\ContosoMaintenance.Functions.csproj", "{0980AA2E-1C59-4AD4-A8B4-C38C8676F323}"
|
||||
EndProject
|
||||
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "ContosoMaintenance.Bot.WebApp", "Backend\BotBackend\ContosoMaintenance.Bot.WebApp.csproj", "{34B405E5-E0D0-47FE-B3E2-2C770E5983EF}"
|
||||
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -180,6 +182,7 @@ Global
|
|||
{0980AA2E-1C59-4AD4-A8B4-C38C8676F323}.ReleaseBackend|iPhone.Build.0 = Release|Any CPU
|
||||
{0980AA2E-1C59-4AD4-A8B4-C38C8676F323}.ReleaseBackend|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{0980AA2E-1C59-4AD4-A8B4-C38C8676F323}.ReleaseBackend|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
|
||||
{34B405E5-E0D0-47FE-B3E2-2C770E5983EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{34B405E5-E0D0-47FE-B3E2-2C770E5983EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{34B405E5-E0D0-47FE-B3E2-2C770E5983EF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
|
@ -219,6 +222,7 @@ Global
|
|||
{61BFA852-2AAC-42BB-9073-B8857D45FE3A} = {9F0FD859-1134-4C77-99E5-83703A2DE5A2}
|
||||
{0980AA2E-1C59-4AD4-A8B4-C38C8676F323} = {A5E6EEE2-C985-4C48-A6FD-BD95BFAA25EA}
|
||||
{34B405E5-E0D0-47FE-B3E2-2C770E5983EF} = {140A5FB1-CD49-4998-8196-74EF067452B3}
|
||||
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {60FF5FF1-44FA-4082-8169-95F16F23BE13}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using ContosoFieldService.Abstractions;
|
||||
using ContosoFieldService.Helpers;
|
||||
using ContosoFieldService.PageModels;
|
||||
using ContosoFieldService.ViewModels;
|
||||
using FreshMvvm;
|
||||
using Microsoft.AppCenter;
|
||||
using Microsoft.AppCenter.Analytics;
|
||||
|
@ -41,18 +41,18 @@ namespace ContosoFieldService
|
|||
tabbedNavigation.BarTextColor = (Color)Current.Resources["AccentColor"];
|
||||
|
||||
// Add first level navigationpages as tabs
|
||||
tabbedNavigation.AddTab<JobsPageModel>("Jobs", "icon_jobs.png");
|
||||
tabbedNavigation.AddTab<PartsPageModel>("Parts", "icon_parts.png");
|
||||
tabbedNavigation.AddTab<ProfilePageModel>("Me", "icon_user.png");
|
||||
tabbedNavigation.AddTab<JobsViewModel>("Jobs", "icon_jobs.png");
|
||||
tabbedNavigation.AddTab<PartsViewModel>("Parts", "icon_parts.png");
|
||||
tabbedNavigation.AddTab<ProfileViewModel>("Me", "icon_user.png");
|
||||
MainPage = tabbedNavigation;
|
||||
}
|
||||
else
|
||||
{
|
||||
var navContainer = new CustomAndroidNavigation("AndroidNavigation");
|
||||
navContainer.Init("Menu", "hamburger.png");
|
||||
navContainer.AddPage<JobsPageModel>("Jobs");
|
||||
navContainer.AddPage<PartsPageModel>("Parts");
|
||||
navContainer.AddPage<ProfilePageModel>("Me");
|
||||
navContainer.AddPage<JobsViewModel>("Jobs");
|
||||
navContainer.AddPage<PartsViewModel>("Parts");
|
||||
navContainer.AddPage<ProfileViewModel>("Me");
|
||||
MainPage = navContainer;
|
||||
}
|
||||
}
|
||||
|
@ -103,5 +103,19 @@ namespace ContosoFieldService
|
|||
{
|
||||
// Handle when your app resumes
|
||||
}
|
||||
|
||||
protected override void OnAppLinkRequestReceived(Uri uri)
|
||||
{
|
||||
var data = uri.ToString().ToLowerInvariant();
|
||||
//only if deep linking
|
||||
if (!data.Contains("/parts/"))
|
||||
return;
|
||||
|
||||
var id = data.Substring(data.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
||||
|
||||
//Navigate based on id here.
|
||||
|
||||
base.OnAppLinkRequestReceived(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
<PackageReference Include="Refractored.MvvmHelpers" Version="1.3.0" />
|
||||
<PackageReference Include="Humanizer" Version="2.2.0" />
|
||||
<PackageReference Include="Corcav.Behaviors" Version="2.3.7" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.3.4" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Transformations" Version="2.3.4" />
|
||||
<PackageReference Include="Xam.Plugin.Geolocator" Version="4.2.0" />
|
||||
<PackageReference Include="Polly" Version="5.8.0" />
|
||||
<PackageReference Include="Plugin.VersionTracking" Version="2.1.0" />
|
||||
|
@ -50,19 +52,18 @@
|
|||
<PackageReference Include="MonkeyCache" Version="0.1.0.1-beta" />
|
||||
<PackageReference Include="MonkeyCache.FileStore" Version="0.1.0.1-beta" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.2.1" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.3.5" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Transformations" Version="2.3.5" />
|
||||
<PackageReference Include="Plugin.Share" Version="7.1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Pages\" />
|
||||
<Folder Include="PageModels\" />
|
||||
<Folder Include="ViewModels\" />
|
||||
<Folder Include="Helpers\" />
|
||||
<Folder Include="Resources\" />
|
||||
<Folder Include="Models\" />
|
||||
<Folder Include="Services\" />
|
||||
<Folder Include="Pages\Jobs\" />
|
||||
<Folder Include="PageModels\Jobs\" />
|
||||
<Folder Include="PageModels\Android\" />
|
||||
<Folder Include="ViewModels\Jobs\" />
|
||||
<Folder Include="ViewModels\Android\" />
|
||||
<Folder Include="Pages\Android\" />
|
||||
<Folder Include="Pages\Profile\" />
|
||||
<Folder Include="Abstractions\" />
|
||||
|
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ContosoFieldService.PageModels.Android;
|
||||
using ContosoFieldService.ViewModels.Android;
|
||||
using FormsToolkit;
|
||||
using FreshMvvm;
|
||||
using Xamarin.Forms;
|
||||
|
@ -71,7 +71,7 @@ namespace ContosoFieldService.Helpers
|
|||
|
||||
protected virtual void CreateMenuPage(string menuPageTitle, string menuIcon = null)
|
||||
{
|
||||
var menuPage = FreshPageModelResolver.ResolvePageModel<MenuPageModel>();
|
||||
var menuPage = FreshPageModelResolver.ResolvePageModel<MenuViewModel>();
|
||||
menuPage.Title = menuPageTitle;
|
||||
|
||||
MessagingService.Current.Subscribe<string>("NavigationTriggered", (x, args) =>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using ContosoFieldService.Models;
|
||||
using MvvmHelpers;
|
||||
using ContosoFieldService.PageModels;
|
||||
using ContosoFieldService.ViewModels;
|
||||
using System.Linq;
|
||||
|
||||
namespace ContosoFieldService.Helpers
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using ContosoFieldService.Models;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace ContosoFieldService.Helpers
|
||||
{
|
||||
|
@ -20,5 +24,59 @@ namespace ContosoFieldService.Helpers
|
|||
|
||||
return $"https://www.gravatar.com/avatar/{hash}?s=512";
|
||||
}
|
||||
|
||||
public static FormattedString ConvertNameToFormattedString(this Job job)
|
||||
{
|
||||
//We want to return a FormattedString which is a Xamarin.Forms Type that allows us to style text elements
|
||||
var formattedString = new FormattedString();
|
||||
|
||||
//We'll use regex to nd content between square brackets [contents]
|
||||
var regexPattern = @"\[(\w*)\]";
|
||||
|
||||
//Lets create a MatchCollection which will contain any matches from our job.name.
|
||||
var patternMatches = Regex.Matches(job.Name, regexPattern);
|
||||
System.Diagnostics.Debug.WriteLine($"Text: {job.Name}");
|
||||
|
||||
|
||||
//If the name doesn't contain a matches then we just a default FormattedString with the name set. No extra work is required.
|
||||
if (patternMatches.Count == 0)
|
||||
{
|
||||
formattedString = new FormattedString { Spans = { new Span { Text = job.Name } } };
|
||||
}
|
||||
else
|
||||
{
|
||||
//We create a list of matched wordsready for use in building the FormattedStrings property.
|
||||
var highlightedWords = new List<string>();
|
||||
|
||||
//We loop through the matches and copy the values to a list of strings for easier use.
|
||||
foreach (Match match in patternMatches)
|
||||
{
|
||||
highlightedWords.Add(RemoveBrackets(match.Value));
|
||||
}
|
||||
|
||||
//We split the name input parts based on our RegEx. "Hello [World]" would become an array of string containing two items, "Hello" and "World";
|
||||
var splitList = Regex.Split(job.Name, regexPattern);
|
||||
|
||||
//We then loop through each subString and add a span, checking that the contents isn't contained in the highlightedWords property.
|
||||
foreach (var subString in splitList)
|
||||
{
|
||||
if (highlightedWords.Contains(subString) == true)
|
||||
//We have found that the text is a highlighted word and thus needs to be bold.
|
||||
formattedString.Spans.Add(new Span { Text = subString, FontAttributes = FontAttributes.Bold });
|
||||
else
|
||||
//The text isn't a highlighted item so we
|
||||
formattedString.Spans.Add(new Span { Text = subString });
|
||||
}
|
||||
}
|
||||
return formattedString;
|
||||
}
|
||||
|
||||
static string RemoveBrackets(string input)
|
||||
{
|
||||
var removedPreTag = input.Replace("[", "");
|
||||
var removedPostTag = removedPreTag.Replace("]", "");
|
||||
return removedPostTag;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using ContosoFieldService.Helpers;
|
||||
using ContosoFieldService.PageModels;
|
||||
using ContosoFieldService.ViewModels;
|
||||
using Xamarin.Forms;
|
||||
using ContosoFieldService.Pages;
|
||||
|
||||
|
@ -12,16 +12,16 @@ namespace ContosoFieldService
|
|||
/// </summary>
|
||||
public static class PageModelLocator
|
||||
{
|
||||
static JobsPageModel jobsPageModel;
|
||||
public static JobsPageModel JobsPageModel => jobsPageModel ?? (jobsPageModel = new JobsPageModel { Jobs = DummyData.GetGroupedDummyJobs() });
|
||||
static JobDetailsPageModel jobDetailsPageModel;
|
||||
public static JobDetailsPageModel JobDetailsPageModel
|
||||
static JobsViewModel jobsPageModel;
|
||||
public static JobsViewModel JobsPageModel => jobsPageModel ?? (jobsPageModel = new JobsViewModel { Jobs = DummyData.GetGroupedDummyJobs() });
|
||||
static JobDetailsViewModel jobDetailsPageModel;
|
||||
public static JobDetailsViewModel JobDetailsPageModel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (jobDetailsPageModel == null)
|
||||
{
|
||||
jobDetailsPageModel = new JobDetailsPageModel();
|
||||
jobDetailsPageModel = new JobDetailsViewModel();
|
||||
jobDetailsPageModel.Init(DummyData.GetDummyJobs().First());
|
||||
}
|
||||
|
||||
|
@ -29,16 +29,16 @@ namespace ContosoFieldService
|
|||
}
|
||||
}
|
||||
|
||||
static PartsPageModel partsPageModel;
|
||||
public static PartsPageModel PartsPageModel => partsPageModel ?? (partsPageModel = new PartsPageModel { Parts = DummyData.GetDummyParts() });
|
||||
static PartDetailsPageModel partDetailsPageModel;
|
||||
public static PartDetailsPageModel PartDetailsPageModel
|
||||
static PartsViewModel partsPageModel;
|
||||
public static PartsViewModel PartsPageModel => partsPageModel ?? (partsPageModel = new PartsViewModel { Parts = DummyData.GetDummyParts() });
|
||||
static PartDetailsViewModel partDetailsPageModel;
|
||||
public static PartDetailsViewModel PartDetailsPageModel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (partDetailsPageModel == null)
|
||||
{
|
||||
partDetailsPageModel = new PartDetailsPageModel();
|
||||
partDetailsPageModel = new PartDetailsViewModel();
|
||||
partDetailsPageModel.Init(DummyData.GetDummyParts().First());
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ namespace ContosoFieldService
|
|||
}
|
||||
}
|
||||
|
||||
static SettingsPageModel settingsPageModel;
|
||||
public static SettingsPageModel SettingsPageModel = settingsPageModel ?? (settingsPageModel = new SettingsPageModel());
|
||||
static SettingsViewModel settingsPageModel;
|
||||
public static SettingsViewModel SettingsPageModel = settingsPageModel ?? (settingsPageModel = new SettingsViewModel());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ContosoFieldService.Models
|
||||
{
|
||||
public class GeoPoint
|
||||
{
|
||||
[JsonProperty("longitude")]
|
||||
public double Longitude { get; set; }
|
||||
|
||||
[JsonProperty("latitude")]
|
||||
public double Latitude { get; set; }
|
||||
|
||||
|
||||
double[] coordinates;
|
||||
|
||||
/// <summary>
|
||||
/// This is here as a small hack due to ensure compatibilty between old data in our DB and new data.
|
||||
/// </summary>
|
||||
/// <value>The coordinates.</value>
|
||||
[Obsolete("Coordinates is deprecated, please use the Longitude and Latitude properties instead.")]
|
||||
[JsonProperty("coordinates")]
|
||||
public double[] Coordinates
|
||||
{
|
||||
get
|
||||
{
|
||||
return coordinates;
|
||||
}
|
||||
set
|
||||
{
|
||||
coordinates = value;
|
||||
Latitude = coordinates[0];
|
||||
Longitude = coordinates[1];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Xamarin.Forms;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Linq;
|
||||
using ContosoFieldService.Helpers;
|
||||
|
||||
namespace ContosoFieldService.Models
|
||||
{
|
||||
|
@ -25,8 +29,18 @@ namespace ContosoFieldService.Models
|
|||
public Location Address { get; set; }
|
||||
|
||||
[JsonProperty("photos")]
|
||||
public List<Photo> Photos { get; set; }
|
||||
}
|
||||
public List<Photo> Photos { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public FormattedString NameAsFormattedString
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ConvertNameToFormattedString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum JobType
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using Microsoft.Azure.Documents.Spatial;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ContosoFieldService.Models
|
||||
|
@ -19,6 +18,6 @@ namespace ContosoFieldService.Models
|
|||
public string ZipCode { get; set; }
|
||||
|
||||
[JsonProperty("point")]
|
||||
public Point GeoPosition { get; set; }
|
||||
public GeoPoint GeoPosition { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
using System;
|
||||
using FreshMvvm;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
{
|
||||
public class BotPageModel : FreshBasePageModel
|
||||
{
|
||||
public BotPageModel()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,6 +18,15 @@
|
|||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem
|
||||
x:Name="btnAddJob"
|
||||
AutomationId="btnAddJob"
|
||||
Icon="icon_share.png"
|
||||
Command="{Binding ShareJobClicked}"/>
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
|
||||
<ScrollView>
|
||||
<StackLayout>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using Xamarin.Forms.Maps;
|
||||
using ContosoFieldService.PageModels;
|
||||
using ContosoFieldService.ViewModels;
|
||||
|
||||
namespace ContosoFieldService.Pages
|
||||
{
|
||||
|
@ -18,10 +18,10 @@ namespace ContosoFieldService.Pages
|
|||
base.OnAppearing();
|
||||
|
||||
// Setup map
|
||||
var pageModel = BindingContext as JobDetailsPageModel;
|
||||
if (pageModel?.Point?.Position?.Latitude != null && pageModel?.Point?.Position?.Longitude != null)
|
||||
var pageModel = BindingContext as JobDetailsViewModel;
|
||||
if (pageModel?.Point?.Latitude != null && pageModel?.Point?.Longitude != null)
|
||||
{
|
||||
var pos = new Position(pageModel.Point.Position.Latitude, pageModel.Point.Position.Longitude);
|
||||
var pos = new Position(pageModel.Point.Latitude, pageModel.Point.Longitude);
|
||||
|
||||
// Move map to point
|
||||
mapView.IsVisible = true;
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
FontFamily="{StaticResource FontFamilyRegular}"
|
||||
FontSize="{StaticResource FontSizeRegular}"
|
||||
TextColor="{StaticResource TextColorItem}"
|
||||
Text="{Binding Name}"
|
||||
FormattedText="{Binding NameAsFormattedString}"
|
||||
LineBreakMode="TailTruncation" />
|
||||
|
||||
<Label
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using ContosoFieldService.PageModels;
|
||||
using ContosoFieldService.ViewModels;
|
||||
using System.Linq;
|
||||
|
||||
namespace ContosoFieldService.Pages
|
||||
|
|
|
@ -51,11 +51,11 @@ namespace ContosoFieldService.Services
|
|||
// TODO: THERE IS A BUG WITH GEOSPARTIAL DATA AT THE MOMENT
|
||||
// ----
|
||||
// If the data isn't too old, we'll go ahead and return it rather than call the backend again.
|
||||
//if (!Barrel.Current.IsExpired(key) && Barrel.Current.Exists(key))
|
||||
//{
|
||||
// var jobs = Barrel.Current.Get<IEnumerable<Job>>(key);
|
||||
// return jobs.ToList();
|
||||
//}
|
||||
if (!Barrel.Current.IsExpired(key) && Barrel.Current.Exists(key))
|
||||
{
|
||||
var jobs = Barrel.Current.Get<IEnumerable<Job>>(key);
|
||||
return jobs.ToList();
|
||||
}
|
||||
|
||||
// Create an instance of the Refit RestService for the job interface.
|
||||
var contosoMaintenanceApi = RestService.For<IJobServiceAPI>(Helpers.Constants.BaseUrl);
|
||||
|
@ -65,7 +65,7 @@ namespace ContosoFieldService.Services
|
|||
if (pollyResult.Result != null)
|
||||
{
|
||||
// Save jobs into the cache
|
||||
Barrel.Current.Add(key, pollyResult.Result, TimeSpan.FromSeconds(5));
|
||||
Barrel.Current.Add(key, pollyResult.Result, TimeSpan.FromMinutes(5));
|
||||
return pollyResult.Result;
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,7 @@ namespace ContosoFieldService.Services
|
|||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public async Task<Job> CreateJobAsync(Job job)
|
||||
|
|
|
@ -4,16 +4,16 @@ using FormsToolkit;
|
|||
using FreshMvvm;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace ContosoFieldService.PageModels.Android
|
||||
namespace ContosoFieldService.ViewModels.Android
|
||||
{
|
||||
public class MenuPageModel : FreshBasePageModel
|
||||
public class MenuViewModel : FreshBasePageModel
|
||||
{
|
||||
public ICommand NavigateCommand { get; set; }
|
||||
|
||||
public List<MenuItem> MenuItems { get; set; }
|
||||
public MenuItem SelectedItem { get; set; }
|
||||
|
||||
public MenuPageModel()
|
||||
public MenuViewModel()
|
||||
{
|
||||
NavigateCommand = new Command(NavigateToPageModel);
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using FreshMvvm;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class DashboardPageModel : FreshBasePageModel
|
||||
public class DashboardViewModel : FreshBasePageModel
|
||||
{
|
||||
bool showLogin;
|
||||
protected override void ViewIsAppearing(object sender, EventArgs e)
|
||||
|
@ -12,7 +12,7 @@ namespace ContosoFieldService.PageModels
|
|||
if (showLogin)
|
||||
{
|
||||
showLogin = false;
|
||||
CoreMethods.PushPageModel<LoginPageModel>(null, true, false);
|
||||
CoreMethods.PushPageModel<LoginViewModel>(null, true, false);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,9 +7,9 @@ using Xamarin.Forms;
|
|||
using Spatial = Microsoft.Azure.Documents.Spatial;
|
||||
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class CreateNewJobPageModel : FreshBasePageModel
|
||||
public class CreateNewJobViewModel : FreshBasePageModel
|
||||
{
|
||||
#region Bindable Properties
|
||||
public string Name { get; set; }
|
||||
|
@ -42,7 +42,7 @@ namespace ContosoFieldService.PageModels
|
|||
try
|
||||
{
|
||||
var location = await Plugin.Geolocator.CrossGeolocator.Current.GetPositionAsync();
|
||||
job.Address = new Location() { GeoPosition = new Spatial.Point(location.Longitude, location.Latitude) };
|
||||
job.Address = new Location() { GeoPosition = new GeoPoint(){Longitude = location.Longitude, Latitude = location.Latitude} };
|
||||
|
||||
job = await jobApiService.CreateJobAsync(job);
|
||||
Analytics.TrackEvent("New Job Created");
|
|
@ -1,13 +1,14 @@
|
|||
using System;
|
||||
using ContosoFieldService.Models;
|
||||
using FreshMvvm;
|
||||
using Humanizer;
|
||||
using Microsoft.Azure.Documents.Spatial;
|
||||
using Humanizer;
|
||||
using Plugin.Share;
|
||||
using Plugin.Share.Abstractions;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class JobDetailsPageModel : FreshBasePageModel
|
||||
public class JobDetailsViewModel : FreshBasePageModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Details { get; set; }
|
||||
|
@ -15,25 +16,26 @@ namespace ContosoFieldService.PageModels
|
|||
public string DueDate { get; set; }
|
||||
public string ContactName { get; set; }
|
||||
public string CompanyName { get; set; }
|
||||
public Microsoft.Azure.Documents.Spatial.Point Point { get; set; }
|
||||
public GeoPoint Point { get; set; }
|
||||
|
||||
Job CurrentJob;
|
||||
Job selectedJob;
|
||||
public override void Init(object initData)
|
||||
{
|
||||
if (initData != null)
|
||||
{
|
||||
CurrentJob = (Job)initData;
|
||||
Name = CurrentJob.Name;
|
||||
Details = CurrentJob.Details;
|
||||
selectedJob = (Job)initData;
|
||||
Name = selectedJob.Name;
|
||||
Details = selectedJob.Details;
|
||||
DueDate = DateTime.Now.Humanize();
|
||||
|
||||
Age = CurrentJob.CreatedAt.Humanize();
|
||||
Details = string.IsNullOrEmpty(CurrentJob.Details) ? "Not Supplied" : CurrentJob.Details;
|
||||
Point = CurrentJob?.Address?.GeoPosition;
|
||||
Age = selectedJob.CreatedAt.Humanize();
|
||||
Details = string.IsNullOrEmpty(selectedJob.Details) ? "Not Supplied" : selectedJob.Details;
|
||||
Point = selectedJob?.Address?.GeoPosition;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentJob = new Job();
|
||||
selectedJob = new Job();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,9 +45,28 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
return new Command(async () =>
|
||||
{
|
||||
await CoreMethods.PushPageModel<WorkingJobPageModel>(CurrentJob, true, true);
|
||||
await CoreMethods.PushPageModel<WorkingJobViewModel>(selectedJob, true, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Command ShareJobClicked
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Command(async () =>
|
||||
{
|
||||
if (!CrossShare.IsSupported)
|
||||
return;
|
||||
|
||||
await CrossShare.Current.Share(new ShareMessage
|
||||
{
|
||||
Title = selectedJob.Name,
|
||||
Text = selectedJob.Details,
|
||||
Url = $"{Helpers.Constants.BaseUrl}job/{selectedJob.Id}"
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Command EditJobClicked
|
||||
|
@ -69,7 +90,7 @@ namespace ContosoFieldService.PageModels
|
|||
if ("Delete" == await CoreMethods.DisplayActionSheet("You're going to delete this job and it'll be embrassing for all if we need to restore it...", "Canel", "Delete"))
|
||||
{
|
||||
var jobsService = new Services.JobsAPIService();
|
||||
var deletedJob = await jobsService.DeleteJobByIdAsync(CurrentJob.Id);
|
||||
var deletedJob = await jobsService.DeleteJobByIdAsync(selectedJob.Id);
|
||||
if (deletedJob != null)
|
||||
{
|
||||
await CoreMethods.PopPageModel(deletedJob);
|
||||
|
@ -89,10 +110,12 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
return new Command(async () =>
|
||||
{
|
||||
await CoreMethods.PushPageModel<PartsPageModel>();
|
||||
await CoreMethods.PushPageModel<PartsViewModel>();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -10,9 +10,9 @@ using System.Collections.Generic;
|
|||
using System.Runtime.CompilerServices;
|
||||
using MonkeyCache.FileStore;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class JobsPageModel : FreshBasePageModel
|
||||
public class JobsViewModel : FreshBasePageModel
|
||||
{
|
||||
#region Bindable Properties
|
||||
public ObservableRangeCollection<GroupedJobs> Jobs { get; set; }
|
||||
|
@ -86,7 +86,7 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
return new Command<Job>(async (job) =>
|
||||
{
|
||||
await CoreMethods.PushPageModel<JobDetailsPageModel>(selectedJob);
|
||||
await CoreMethods.PushPageModel<JobDetailsViewModel>(selectedJob);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
new GroupedJobs("Search Results", searchResults)
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
return new Command(async () =>
|
||||
{
|
||||
await CoreMethods.PushPageModel<CreateNewJobPageModel>(null, false, true);
|
||||
await CoreMethods.PushPageModel<CreateNewJobViewModel>(null, false, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ namespace ContosoFieldService.PageModels
|
|||
base.ViewIsAppearing(sender, e);
|
||||
|
||||
if (Helpers.Settings.LoginViewShown == false)
|
||||
await CoreMethods.PushPageModel<LoginPageModel>(null, true, true);
|
||||
await CoreMethods.PushPageModel<LoginViewModel>(null, true, true);
|
||||
|
||||
await ReloadData(true);
|
||||
}
|
|
@ -10,9 +10,9 @@ using Plugin.Media.Abstractions;
|
|||
using ContosoFieldService.Models;
|
||||
using ContosoFieldService.Services;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class WorkingJobPageModel : FreshBasePageModel
|
||||
public class WorkingJobViewModel : FreshBasePageModel
|
||||
{
|
||||
JobsAPIService jobService = new JobsAPIService();
|
||||
PhotoAPIService photoService = new PhotoAPIService();
|
|
@ -6,9 +6,9 @@ using System;
|
|||
using ContosoFieldService.Services;
|
||||
using ContosoFieldService.Helpers;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class LoginPageModel : FreshBasePageModel
|
||||
public class LoginViewModel : FreshBasePageModel
|
||||
{
|
||||
readonly AuthenticationService authenticationService;
|
||||
|
||||
|
@ -45,7 +45,7 @@ namespace ContosoFieldService.PageModels
|
|||
await CoreMethods.PopPageModel(true, true);
|
||||
}));
|
||||
|
||||
public LoginPageModel()
|
||||
public LoginViewModel()
|
||||
{
|
||||
authenticationService = new AuthenticationService();
|
||||
}
|
|
@ -3,9 +3,9 @@ using FreshMvvm;
|
|||
using ContosoFieldService.Models;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class PartDetailsPageModel : FreshBasePageModel
|
||||
public class PartDetailsViewModel : FreshBasePageModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Manufacturer { get; set; }
|
||||
|
@ -30,6 +30,7 @@ namespace ContosoFieldService.PageModels
|
|||
PartNumber = Part.PartNumber;
|
||||
PriceInUSD = Part.PriceInUSD;
|
||||
ImageSource = Part.ImageSource;
|
||||
CreateDeepLinkEntry();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -48,5 +49,27 @@ namespace ContosoFieldService.PageModels
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CreateDeepLinkEntry()
|
||||
{
|
||||
var url = $"{Helpers.Constants.BaseUrl}/part/{Part.Id}";
|
||||
|
||||
var entry = new AppLinkEntry
|
||||
{
|
||||
Title = Part.Name,
|
||||
Description = Part.Manufacturer,
|
||||
AppLinkUri = new Uri(url, UriKind.RelativeOrAbsolute),
|
||||
IsLinkActive = true,
|
||||
Thumbnail = Xamarin.Forms.ImageSource.FromFile("icon_greentool.png")
|
||||
};
|
||||
|
||||
entry.KeyValues.Add("contentType", "Parts");
|
||||
entry.KeyValues.Add("appName", "Field Service");
|
||||
entry.KeyValues.Add("companyName", "Contoso Maintenance");
|
||||
|
||||
Application.Current.AppLinks.RegisterLink(entry);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -6,9 +6,9 @@ using Xamarin.Forms;
|
|||
using ContosoFieldService.Services;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class PartsPageModel : FreshBasePageModel
|
||||
public class PartsViewModel : FreshBasePageModel
|
||||
{
|
||||
public ObservableRangeCollection<Part> Parts { get; set; }
|
||||
public bool IsRefreshing
|
||||
|
@ -59,7 +59,7 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
return new Command<Part>(async (part) =>
|
||||
{
|
||||
await CoreMethods.PushPageModel<PartDetailsPageModel>(part);
|
||||
await CoreMethods.PushPageModel<PartDetailsViewModel>(part);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
return new Command(async () =>
|
||||
{
|
||||
await CoreMethods.PushPageModel<CreateNewJobPageModel>(null, true, true);
|
||||
await CoreMethods.PushPageModel<CreateNewJobViewModel>(null, true, true);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using FreshMvvm;
|
||||
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class BotViewModel : FreshBasePageModel
|
||||
{
|
||||
public BotViewModel()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@ using Microsoft.AppCenter.Analytics;
|
|||
using Xamarin.Forms;
|
||||
using ContosoFieldService.Services;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class ProfilePageModel : FreshBasePageModel
|
||||
public class ProfileViewModel : FreshBasePageModel
|
||||
{
|
||||
readonly AuthenticationService authenticationService;
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
Helpers.Settings.LoginViewShown = true;
|
||||
Analytics.TrackEvent("User chatted to bot");
|
||||
await CoreMethods.PushPageModel<BotPageModel>(true);
|
||||
await CoreMethods.PushPageModel<BotViewModel>(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -39,12 +39,12 @@ namespace ContosoFieldService.PageModels
|
|||
{
|
||||
Helpers.Settings.LoginViewShown = true;
|
||||
Analytics.TrackEvent("User chatted to bot");
|
||||
await CoreMethods.PushPageModel<SettingsPageModel>(true);
|
||||
await CoreMethods.PushPageModel<SettingsViewModel>(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ProfilePageModel()
|
||||
public ProfileViewModel()
|
||||
{
|
||||
authenticationService = new AuthenticationService();
|
||||
}
|
|
@ -6,9 +6,9 @@ using Microsoft.AppCenter.Push;
|
|||
using Plugin.VersionTracking;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace ContosoFieldService.PageModels
|
||||
namespace ContosoFieldService.ViewModels
|
||||
{
|
||||
public class SettingsPageModel : FreshBasePageModel
|
||||
public class SettingsViewModel : FreshBasePageModel
|
||||
{
|
||||
string baseUrl;
|
||||
public string BaseUrl
|
||||
|
@ -90,7 +90,7 @@ namespace ContosoFieldService.PageModels
|
|||
}
|
||||
}
|
||||
|
||||
public SettingsPageModel()
|
||||
public SettingsViewModel()
|
||||
{
|
||||
Version = $"{CrossVersionTracking.Current.CurrentVersion} (Build {CrossVersionTracking.Current.CurrentBuild})";
|
||||
|
|
@ -30,8 +30,6 @@
|
|||
<DeviceSpecificBuild>false</DeviceSpecificBuild>
|
||||
<MtouchVerbosity>
|
||||
</MtouchVerbosity>
|
||||
<CodesignProvision>
|
||||
</CodesignProvision>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
@ -41,14 +39,14 @@
|
|||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodesignKey>iPhone Distribution: Xamarin Inc</CodesignKey>
|
||||
<CodesignKey>iPhone Developer: Michael James (354MN7UPEZ)</CodesignKey>
|
||||
<MtouchFloat32>true</MtouchFloat32>
|
||||
<CodesignEntitlements>Entitlements.prod.plist</CodesignEntitlements>
|
||||
<MtouchLink>SdkOnly</MtouchLink>
|
||||
<MtouchArch>ARM64</MtouchArch>
|
||||
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||
<MtouchVerbosity></MtouchVerbosity>
|
||||
<CodesignProvision>Contoso Maintenance In-House</CodesignProvision>
|
||||
<CodesignProvision>VS: WildCard Development</CodesignProvision>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
@ -65,7 +63,7 @@
|
|||
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||
<MtouchVerbosity>
|
||||
</MtouchVerbosity>
|
||||
<CodesignProvision>VS: com.microsoft.gbb.contosomaintenance Development</CodesignProvision>
|
||||
<CodesignProvision>VS: WildCard Development</CodesignProvision>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -88,7 +86,6 @@
|
|||
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||
<MtouchVerbosity>
|
||||
</MtouchVerbosity>
|
||||
<CodesignProvision>Contoso Maintenance Development</CodesignProvision>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugBackend|AnyCPU' ">
|
||||
<Optimize>false</Optimize>
|
||||
|
@ -107,10 +104,11 @@
|
|||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<CodesignKey>iPhone Developer: Michael James (354MN7UPEZ)</CodesignKey>
|
||||
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
|
||||
<MtouchVerbosity>
|
||||
</MtouchVerbosity>
|
||||
<CodesignProvision>VS: WildCard Development</CodesignProvision>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
|
@ -478,6 +476,9 @@
|
|||
<BundleResource Include="Resources\icon_bot.png" />
|
||||
<BundleResource Include="Resources\icon_usersettings%402x.png" />
|
||||
<BundleResource Include="Resources\photoupload.json" />
|
||||
<BundleResource Include="Resources\icon_share.png" />
|
||||
<BundleResource Include="Resources\icon_share%402x.png" />
|
||||
<BundleResource Include="Resources\icon_share%403x.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||
<Import Project="..\..\packages\NETStandard.Library.2.0.1\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\..\packages\NETStandard.Library.2.0.1\build\netstandard2.0\NETStandard.Library.targets')" />
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
<key>CFBundleName</key>
|
||||
<string>Field Service</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.contoso.contosomaintenance</string>
|
||||
<string>com.microsoft.contosomaintenance</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<string>1.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 570 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.0 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.4 KiB |
|
@ -71,6 +71,7 @@
|
|||
<package id="NETStandard.Library" version="2.0.1" targetFramework="xamarinios10" />
|
||||
<package id="Newtonsoft.Json" version="11.0.1" targetFramework="xamarinios10" />
|
||||
<package id="Plugin.Permissions" version="2.2.1" targetFramework="xamarinios10" />
|
||||
<package id="Plugin.Share" version="7.1.1" targetFramework="xamarinios10" />
|
||||
<package id="Polly" version="5.8.0" targetFramework="xamarinios10" />
|
||||
<package id="Refit" version="4.3.0" targetFramework="xamarinios10" />
|
||||
<package id="Refractored.MvvmHelpers" version="1.3.0" targetFramework="xamarinios10" />
|
||||
|
|
Двоичные данные
Resources/Contoso Maintenance.paw
Двоичные данные
Resources/Contoso Maintenance.paw
Двоичный файл не отображается.
Двоичные данные
Resources/Design/ContosoMaintenance.sketch
Двоичные данные
Resources/Design/ContosoMaintenance.sketch
Двоичный файл не отображается.
|
@ -44,7 +44,7 @@ We opted to use [FreshMvvm](https://github.com/rid00z/FreshMvvm) as our MVVM lib
|
|||
We've tried to keep the platform-specific code to a minimum with the development of this app. This is because we wanted you to see how its possible to create pleasant user experiences while maximising code reuse.
|
||||
|
||||
#### Core Project
|
||||
The core project contains our app's Pages, ViewModels (we call them PageModels), Models and network services.
|
||||
The core project contains our app's Pages (Views), ViewModels, Models and network services.
|
||||
|
||||
As we're using the MVVM architecture, we have a clear separation of concerns within our app.
|
||||
|
||||
|
|
|
@ -356,3 +356,4 @@ There are several cool things you can do with Azure Active Directory, that will
|
|||
- [Add Social Authentication Providers](https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-setup-fb-app)
|
||||
- [Customize the Login UI](https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-ui-customization)
|
||||
- [Enable Multifactor authentication](https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-mfa)
|
||||
- [Login with and existing Azure Active Directory Account](https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-setup-aad-custom)
|
||||
|
|
Загрузка…
Ссылка в новой задаче