Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unfinished ChartStudio Integration #235

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Plotly.NET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plotly.NET.Tests.CSharpCons
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plotly.NET.Tests.CSharp", "tests\Plotly.NET.Tests.CSharp\Plotly.NET.Tests.CSharp.csproj", "{26539796-0C9D-4856-8584-B58BE32CC495}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Plotly.NET.ChartStudio", "src\Plotly.NET.ChartStudio\Plotly.NET.ChartStudio.fsproj", "{9574A266-2AC3-469C-83A6-D2EF72CECFD4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -182,6 +184,12 @@ Global
{26539796-0C9D-4856-8584-B58BE32CC495}.Dotnet|Any CPU.Build.0 = Debug|Any CPU
{26539796-0C9D-4856-8584-B58BE32CC495}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26539796-0C9D-4856-8584-B58BE32CC495}.Release|Any CPU.Build.0 = Release|Any CPU
{9574A266-2AC3-469C-83A6-D2EF72CECFD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9574A266-2AC3-469C-83A6-D2EF72CECFD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9574A266-2AC3-469C-83A6-D2EF72CECFD4}.Dotnet|Any CPU.ActiveCfg = Debug|Any CPU
{9574A266-2AC3-469C-83A6-D2EF72CECFD4}.Dotnet|Any CPU.Build.0 = Debug|Any CPU
{9574A266-2AC3-469C-83A6-D2EF72CECFD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9574A266-2AC3-469C-83A6-D2EF72CECFD4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -197,6 +205,7 @@ Global
{60114ACE-77E6-4A19-9A2F-CB64084174AF} = {EAE25A1F-86FC-426B-803F-1006D1AD06A8}
{1BC73DA0-586F-45C2-BC5B-A70C452A00F0} = {EAE25A1F-86FC-426B-803F-1006D1AD06A8}
{26539796-0C9D-4856-8584-B58BE32CC495} = {EAE25A1F-86FC-426B-803F-1006D1AD06A8}
{9574A266-2AC3-469C-83A6-D2EF72CECFD4} = {0E87E47E-9EDC-4525-AF72-F0E139D54236}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7177F1E1-341C-48AB-9864-6B525FFF7633}
Expand Down
89 changes: 89 additions & 0 deletions src/Plotly.NET.ChartStudio/API.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
namespace Plotly.NET.ChartStudio

open DynamicObj
open System
open System.Runtime.InteropServices
open System.Net.Http
open System.Web

type API() =

static let RESOURCE = "plots"

static member buildURL
(
resource,
[<Optional; DefaultParameterValue("")>] ?id: String,
[<Optional; DefaultParameterValue("")>] ?route: String
) =

let config = Config.getConfigFile ()

let baseURL =
match config.TryGetValue "plotly_api_domain" with
| Some apiDomain -> string apiDomain
| _ -> "https://api.plotly.com"

let urlWithID =
match id with
| Some x when (not (String.IsNullOrEmpty(x))) -> $"{baseURL}//v2//{resource}//{x}"
| _ -> $"{baseURL}//v2//{resource}"

let url =
match route with
| Some x when (not (String.IsNullOrEmpty(x))) -> $"{urlWithID}//{route}"
| _ -> $"{urlWithID}"

url

static member create body =
async {
use client = new HttpClient()

let url = API.buildURL RESOURCE
let content = new StringContent(body)
printf "%A" url

let! response = client.PostAsync(url, content) |> Async.AwaitTask

let! body =
response.Content.ReadAsStringAsync()
|> Async.AwaitTask

return
match response.IsSuccessStatusCode with
| true -> Ok body
| false -> Error body
}
|> Async.RunSynchronously

static member retrieve(fid, [<Optional; DefaultParameterValue("")>] ?share_key: String) =
async {
use client = new HttpClient()

let url =
API.buildURL (resource = RESOURCE, id = fid)

let url =
match share_key with
| Some key ->
let query =
HttpUtility.ParseQueryString(String.Empty)

query.Add("share_key", key)

let builder =
new UriBuilder(url, Query = query.ToString())

builder.Uri.ToString()
| _ -> url

let! response = client.GetAsync(url) |> Async.AwaitTask

let! content =
response.Content.ReadAsStringAsync()
|> Async.AwaitTask

return content
}
|> Async.RunSynchronously
55 changes: 55 additions & 0 deletions src/Plotly.NET.ChartStudio/Chart.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace Plotly.NET.ChartStudio

open Plotly.NET
open Plotly.NET.GenericChart
open System.Runtime.InteropServices
open Newtonsoft.Json
open System.Collections

/// Extensions methods from Plotly.NET.ImageExport for the Chart module, supporting the fluent pipeline style
[<AutoOpen>]
module ChartExtensions =
let internal jsonConfig = JsonSerializerSettings()
jsonConfig.ReferenceLoopHandling <- ReferenceLoopHandling.Serialize

type Chart with

[<CompiledName("PostToCloud")>]
static member postToCloud
(
[<Optional; DefaultParameterValue(null)>] ?FileName: string,
[<Optional; DefaultParameterValue(null)>] ?AutoOpen: bool,
[<Optional; DefaultParameterValue(null)>] ?Sharing: string
) =

let extractGridFromFigure (gChart: GenericChart) =
let traces = getTraces gChart

let dataArrays =
[ for trace in traces ->
trace.GetProperties(true)
|> Seq.filter (fun x -> (x.Value :? IEnumerable && not (x.Value :? string))) ]

|> Seq.mapi
(fun i data ->
data
|> Seq.map
(fun kvp ->
{| Name = $"data.{i}.{kvp.Key}"
Data = kvp.Value |}))

printf "%A" dataArrays
()



fun (gChart: GenericChart) ->

extractGridFromFigure gChart

let figure = GenericChart.toFigure gChart

let payload =
JsonConvert.SerializeObject({| figure = figure |}, jsonConfig)

API.create payload
212 changes: 212 additions & 0 deletions src/Plotly.NET.ChartStudio/Config.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
namespace Plotly.NET.ChartStudio

open DynamicObj
open System
open System.Runtime.InteropServices
open System.IO
open Newtonsoft.Json.Linq
open Newtonsoft.Json
open System.Diagnostics

type Credentials() =
inherit DynamicObj()

static let PLOTLY_DIR =
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)

static let CREDENTIALS_FILE = Path.Combine(PLOTLY_DIR, ".credentials")

static member init
(
[<Optional; DefaultParameterValue(null)>] ?Username: string,
[<Optional; DefaultParameterValue(null)>] ?APIKEY: string,
[<Optional; DefaultParameterValue(null)>] ?ProxyUsername: string,
[<Optional; DefaultParameterValue(null)>] ?ProxyPassword: string
) =
Credentials()
|> Credentials.style (
?Username = Username,
?APIKEY = APIKEY,
?ProxyUsername = ProxyUsername,
?ProxyPassword = ProxyPassword
)

static member style
(
[<Optional; DefaultParameterValue(null)>] ?Username: string,
[<Optional; DefaultParameterValue(null)>] ?APIKEY: string,
[<Optional; DefaultParameterValue(null)>] ?ProxyUsername: string,
[<Optional; DefaultParameterValue(null)>] ?ProxyPassword: string
) =
fun (credentials: Credentials) ->

Username
|> DynObj.setValueOpt credentials "username"

APIKEY |> DynObj.setValueOpt credentials "api_key"

ProxyUsername
|> DynObj.setValueOpt credentials "proxy_username"

ProxyPassword
|> DynObj.setValueOpt credentials "proxy_password"

credentials

static member getCredentialsFile() =
try
let json =
JObject.Parse(File.ReadAllText(CREDENTIALS_FILE))

Credentials.init (
string json.["username"],
string json.["api_key"],
string json.["proxy_username"],
string json.["proxy_password"]
)
with
| _ -> Credentials.init ()

static member setCredentialsFile
(
[<Optional; DefaultParameterValue(null)>] ?Username: string,
[<Optional; DefaultParameterValue(null)>] ?APIKEY: string,
[<Optional; DefaultParameterValue(null)>] ?ProxyUsername: string,
[<Optional; DefaultParameterValue(null)>] ?ProxyPassword: string
) =
let text =
Credentials()
|> Credentials.style (
?Username = Username,
?APIKEY = APIKEY,
?ProxyUsername = ProxyUsername,
?ProxyPassword = ProxyPassword
)
|> JsonConvert.SerializeObject

try
File.WriteAllText(CREDENTIALS_FILE, text)
with
| e -> Trace.WriteLine(e.Message)



type Config() =
inherit DynamicObj()

static let PLOTLY_DIR =
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)

static let CONFIG_FILE = Path.Combine(PLOTLY_DIR, ".config")

static member init
(
[<Optional; DefaultParameterValue("https://plotly.com")>] ?Domain: string,
[<Optional; DefaultParameterValue("stream.plotly.com")>] ?StreamingDomain: string,
[<Optional; DefaultParameterValue("https://api.plotly.com")>] ?APIDomain: string,
[<Optional; DefaultParameterValue(true)>] ?SSLVerification: bool,
[<Optional; DefaultParameterValue(false)>] ?ProxyAuthorization: bool,
[<Optional; DefaultParameterValue(true)>] ?WorldReadable: bool,
[<Optional; DefaultParameterValue("public")>] ?Sharing: string,
[<Optional; DefaultParameterValue(true)>] ?AutoOpen: bool
) =
Config()
|> Config.style (
?Domain = Domain,
?StreamingDomain = StreamingDomain,
?APIDomain = APIDomain,
?SSLVerification = SSLVerification,
?ProxyAuthorization = ProxyAuthorization,
?WorldReadable = WorldReadable,
?Sharing = Sharing,
?AutoOpen = AutoOpen
)

static member style
(
[<Optional; DefaultParameterValue(null)>] ?Domain: string,
[<Optional; DefaultParameterValue(null)>] ?StreamingDomain: string,
[<Optional; DefaultParameterValue(null)>] ?APIDomain: string,
[<Optional; DefaultParameterValue(null)>] ?SSLVerification: bool,
[<Optional; DefaultParameterValue(null)>] ?ProxyAuthorization: bool,
[<Optional; DefaultParameterValue(null)>] ?WorldReadable: bool,
[<Optional; DefaultParameterValue(null)>] ?Sharing: string,
[<Optional; DefaultParameterValue(null)>] ?AutoOpen: bool
) =
fun (config: Config) ->

Domain
|> DynObj.setValueOpt config "plotly_domain"

StreamingDomain
|> DynObj.setValueOpt config "plotly_streaming_domain"

APIDomain
|> DynObj.setValueOpt config "plotly_api_domain"

SSLVerification
|> DynObj.setValueOpt config "plotly_ssl_verification"

ProxyAuthorization
|> DynObj.setValueOpt config "plotly_proxy_authorization"

WorldReadable
|> DynObj.setValueOpt config "world_readable"

Sharing |> DynObj.setValueOpt config "sharing"

AutoOpen |> DynObj.setValueOpt config "auto_open"

config

static member getConfigFile() =
let getBool (jtoken: JToken) =
let _, result = bool.TryParse(string jtoken)
result

try
let json =
JObject.Parse(File.ReadAllText(CONFIG_FILE))

Config.init (
string json.["plotly_domain"],
string json.["plotly_streaming_domain"],
string json.["plotly_api_domain"],
getBool <| json.["plotly_ssl_verification"],
getBool <| json.["plotly_proxy_authorization"],
getBool <| json.["world_readable"],
string json.["sharing"],
getBool <| json.["auto_open"]
)
with
| _ -> Config.init ()

static member setConfigFile
(
[<Optional; DefaultParameterValue(null)>] ?Domain: string,
[<Optional; DefaultParameterValue(null)>] ?StreamingDomain: string,
[<Optional; DefaultParameterValue(null)>] ?APIDomain: string,
[<Optional; DefaultParameterValue(null)>] ?SSLVerification: bool,
[<Optional; DefaultParameterValue(null)>] ?ProxyAuthorization: bool,
[<Optional; DefaultParameterValue(null)>] ?WorldReadable: bool,
[<Optional; DefaultParameterValue(null)>] ?Sharing: string,
[<Optional; DefaultParameterValue(null)>] ?AutoOpen: bool
) =
let text =
Config()
|> Config.style (
?Domain = Domain,
?StreamingDomain = StreamingDomain,
?APIDomain = APIDomain,
?SSLVerification = SSLVerification,
?ProxyAuthorization = ProxyAuthorization,
?WorldReadable = WorldReadable,
?Sharing = Sharing,
?AutoOpen = AutoOpen
)
|> JsonConvert.SerializeObject

try
File.WriteAllText(CONFIG_FILE, text)
with
| e -> Trace.WriteLine(e.Message)
Loading