sqlui 0.1.70 → 0.1.72
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.release-version +1 -1
- data/app/github/cache.rb +2 -3
- data/app/github/caching_client.rb +5 -1
- data/app/github/client.rb +28 -1
- data/app/github/file.rb +16 -5
- data/app/github/paths.rb +16 -10
- data/app/github/tree.rb +32 -6
- data/app/github/tree_client.rb +79 -21
- data/app/pigs.rb +124 -0
- data/app/saved_config.rb +4 -1
- data/app/server.rb +86 -33
- data/app/sqlui.rb +36 -1
- data/app/views/databases.erb +50 -29
- data/app/views/error.erb +10 -2
- data/app/views/redirect.erb +20 -0
- data/app/views/sqlui.erb +34 -13
- data/client/resources/favicon.svg +50 -1
- data/client/resources/github.svg +3 -0
- data/client/resources/help.css +1 -1
- data/client/resources/saved.css +96 -0
- data/client/resources/sqlui.css +60 -53
- data/client/resources/sqlui.js +186 -100
- metadata +20 -2
data/app/server.rb
CHANGED
@@ -7,6 +7,7 @@ require 'erb'
|
|
7
7
|
require 'json'
|
8
8
|
require 'prometheus/middleware/collector'
|
9
9
|
require 'prometheus/middleware/exporter'
|
10
|
+
require 'securerandom'
|
10
11
|
require 'sinatra/base'
|
11
12
|
require 'uri'
|
12
13
|
require 'webrick'
|
@@ -14,22 +15,30 @@ require_relative 'database_metadata'
|
|
14
15
|
require_relative 'github/cache'
|
15
16
|
require_relative 'github/caching_client'
|
16
17
|
require_relative 'github/client'
|
18
|
+
require_relative 'github/paths'
|
17
19
|
require_relative 'github/tree'
|
18
20
|
require_relative 'github/tree_client'
|
19
21
|
require_relative 'mysql_types'
|
22
|
+
require_relative 'pigs'
|
20
23
|
require_relative 'sql_parser'
|
21
24
|
require_relative 'sqlui'
|
22
25
|
require_relative 'version'
|
23
26
|
|
24
27
|
# SQLUI Sinatra server.
|
25
28
|
class Server < Sinatra::Base
|
26
|
-
|
27
|
-
|
29
|
+
# An error message and status code.
|
30
|
+
class ClientError < StandardError
|
31
|
+
attr_reader :status
|
32
|
+
|
33
|
+
def initialize(message, status: 400)
|
34
|
+
super(message)
|
35
|
+
@status = status
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
|
-
def self.init_and_run(config, resources_dir, github_cache
|
31
|
-
logger.info("Starting SQLUI v#{Version::SQLUI}")
|
32
|
-
logger.info("Airbrake enabled: #{config.airbrake[:server]&.[](:enabled) || false}")
|
39
|
+
def self.init_and_run(config, resources_dir, github_cache)
|
40
|
+
Sqlui.logger.info("Starting SQLUI v#{Version::SQLUI}")
|
41
|
+
Sqlui.logger.info("Airbrake enabled: #{config.airbrake[:server]&.[](:enabled) || false}")
|
33
42
|
|
34
43
|
WEBrick::HTTPRequest.const_set('MAX_URI_LENGTH', 2 * 1024 * 1024)
|
35
44
|
|
@@ -110,13 +119,37 @@ class Server < Sinatra::Base
|
|
110
119
|
end
|
111
120
|
|
112
121
|
post "#{config.base_url_path}/#{database.url_path}/metadata" do
|
113
|
-
tree =
|
122
|
+
tree = nil
|
114
123
|
if (saved_config = database.saved_config)
|
115
|
-
tree_client = Github::TreeClient.new(
|
116
|
-
|
117
|
-
|
118
|
-
|
124
|
+
tree_client = Github::TreeClient.new(
|
125
|
+
access_token: database.saved_config.token,
|
126
|
+
cache: github_cache,
|
127
|
+
logger: Sqlui.logger
|
128
|
+
)
|
129
|
+
tree = tree_client.get_tree(
|
130
|
+
owner: saved_config.owner,
|
131
|
+
repo: saved_config.repo,
|
132
|
+
ref: saved_config.branch,
|
133
|
+
regex: saved_config.regex
|
134
|
+
)
|
135
|
+
if params[:file]
|
136
|
+
owner, repo, ref, path = Github::Paths.parse_file_path(params[:file])
|
137
|
+
raise ClientError, "invalid owner: #{owner}" unless tree.owner == owner
|
138
|
+
raise ClientError, "invalid repo: #{repo}" unless tree.repo == repo
|
139
|
+
|
140
|
+
requested_tree = tree_client.get_tree(
|
141
|
+
owner: owner,
|
142
|
+
repo: repo,
|
143
|
+
ref: ref,
|
144
|
+
regex: /#{Regexp.escape(path)}/,
|
145
|
+
cache: ref == tree.ref
|
146
|
+
)
|
147
|
+
raise ClientError.new("file not found: #{params[:file]}", status: 404) unless requested_tree[path]
|
148
|
+
|
149
|
+
tree << requested_tree[path]
|
150
|
+
end
|
119
151
|
end
|
152
|
+
|
120
153
|
metadata = database.with_client do |client|
|
121
154
|
{
|
122
155
|
server: "#{config.name} - #{database.display_name}",
|
@@ -125,18 +158,15 @@ class Server < Sinatra::Base
|
|
125
158
|
tables: database.tables,
|
126
159
|
columns: database.columns,
|
127
160
|
joins: database.joins,
|
128
|
-
saved: tree.to_h do |file|
|
129
|
-
comment_lines = file.content.split("\n").take_while do |l|
|
130
|
-
l.start_with?('--')
|
131
|
-
end
|
132
|
-
description = comment_lines.map { |l| l.sub(/^-- */, '') }.join("\n")
|
161
|
+
saved: (tree || {}).to_h do |file|
|
133
162
|
[
|
134
|
-
file.
|
163
|
+
file.full_path,
|
135
164
|
{
|
136
|
-
filename: file.
|
165
|
+
filename: file.full_path,
|
166
|
+
path: file.path,
|
137
167
|
github_url: file.github_url,
|
138
|
-
|
139
|
-
|
168
|
+
contents: file.content,
|
169
|
+
tree_sha: file.tree_sha
|
140
170
|
}
|
141
171
|
]
|
142
172
|
end
|
@@ -151,7 +181,7 @@ class Server < Sinatra::Base
|
|
151
181
|
data = request.body.read
|
152
182
|
request.body.rewind # since Airbrake will read the body on error
|
153
183
|
params.merge!(JSON.parse(data, symbolize_names: true))
|
154
|
-
|
184
|
+
raise ClientError, 'ERROR: missing sql' unless params[:sql]
|
155
185
|
|
156
186
|
variables = params[:variables] || {}
|
157
187
|
queries = find_selected_queries(params[:sql], params[:selection])
|
@@ -232,7 +262,7 @@ class Server < Sinatra::Base
|
|
232
262
|
end
|
233
263
|
|
234
264
|
get "#{config.base_url_path}/#{database.url_path}/download_csv" do
|
235
|
-
|
265
|
+
raise ClientError, 'missing sql' unless params[:sql]
|
236
266
|
|
237
267
|
sql = Base64.decode64(params[:sql]).force_encoding('UTF-8')
|
238
268
|
variables = params.map { |k, v| k[0] == '_' ? [k, v] : nil }.compact.to_h
|
@@ -278,22 +308,51 @@ class Server < Sinatra::Base
|
|
278
308
|
resource_path_map: resource_path_map
|
279
309
|
}
|
280
310
|
end
|
311
|
+
|
312
|
+
post("#{config.base_url_path}/#{database.url_path}/save-file") do
|
313
|
+
raise ClientError, 'saved files disabled' unless (saved_config = database.saved_config)
|
314
|
+
raise ClientError, 'missing base_sha' if (params[:base_sha] || '').strip.empty?
|
315
|
+
raise ClientError, 'missing path' if (params[:path] || '').strip.empty?
|
316
|
+
raise ClientError, 'missing content' if params[:path].nil?
|
317
|
+
|
318
|
+
branch = "sqlui-#{Pigs.generate_phrase}"
|
319
|
+
tree_client = Github::TreeClient.new(
|
320
|
+
access_token: database.saved_config.token,
|
321
|
+
cache: github_cache,
|
322
|
+
logger: Sqlui.logger
|
323
|
+
)
|
324
|
+
tree_client.create_commit_with_file(
|
325
|
+
owner: saved_config.owner,
|
326
|
+
repo: saved_config.repo,
|
327
|
+
base_sha: params[:base_sha],
|
328
|
+
branch: branch,
|
329
|
+
path: params[:path],
|
330
|
+
content: params[:content].gsub("\r\n", "\n"),
|
331
|
+
author_name: database.saved_config.author_name,
|
332
|
+
author_email: database.saved_config.author_email
|
333
|
+
)
|
334
|
+
status 201
|
335
|
+
erb :redirect, locals: {
|
336
|
+
resource_path_map: resource_path_map,
|
337
|
+
location: "https://github.com/#{saved_config.owner}/#{saved_config.repo}/compare/#{branch}"
|
338
|
+
}
|
339
|
+
end
|
281
340
|
end
|
282
341
|
|
283
|
-
error
|
284
|
-
exception
|
285
|
-
stacktrace = exception
|
342
|
+
error do |exception|
|
343
|
+
status exception.is_a?(ClientError) ? exception.status : 500
|
344
|
+
stacktrace = exception.full_message(highlight: false)
|
286
345
|
if request.env['HTTP_ACCEPT'] == 'application/json'
|
287
346
|
headers 'Content-Type' => 'application/json; charset=utf-8'
|
288
|
-
message =
|
347
|
+
message = exception.message.to_s
|
289
348
|
json = { error: message, stacktrace: stacktrace }.compact.to_json
|
290
349
|
body json
|
291
350
|
else
|
292
|
-
message = "#{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
|
293
351
|
erb :error, locals: {
|
294
352
|
resource_path_map: resource_path_map,
|
295
353
|
title: "SQLUI #{message}",
|
296
|
-
|
354
|
+
heading: "#{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}",
|
355
|
+
message: exception.message,
|
297
356
|
stacktrace: stacktrace
|
298
357
|
}
|
299
358
|
end
|
@@ -304,12 +363,6 @@ class Server < Sinatra::Base
|
|
304
363
|
|
305
364
|
private
|
306
365
|
|
307
|
-
def client_error(message, stacktrace: nil)
|
308
|
-
status(400)
|
309
|
-
headers 'Content-Type' => 'application/json; charset=utf-8'
|
310
|
-
body({ error: message, stacktrace: stacktrace }.compact.to_json)
|
311
|
-
end
|
312
|
-
|
313
366
|
def find_selected_queries(full_sql, selection)
|
314
367
|
if selection
|
315
368
|
if selection.include?('-')
|
data/app/sqlui.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'webrick'
|
4
|
+
|
5
|
+
require_relative 'github/cache'
|
3
6
|
require_relative 'sqlui_config'
|
4
7
|
require_relative 'server'
|
5
8
|
require_relative 'version'
|
@@ -9,6 +12,10 @@ class Sqlui
|
|
9
12
|
MAX_ROWS = 100_000
|
10
13
|
MAX_BYTES = 10 * 1_024 * 1_024 # 10 MB
|
11
14
|
|
15
|
+
def self.logger
|
16
|
+
@logger ||= WEBrick::Log.new
|
17
|
+
end
|
18
|
+
|
12
19
|
def initialize(config_file)
|
13
20
|
raise 'you must specify a configuration file' unless config_file
|
14
21
|
raise 'configuration file does not exist' unless File.exist?(config_file)
|
@@ -21,7 +28,7 @@ class Sqlui
|
|
21
28
|
end
|
22
29
|
|
23
30
|
def run
|
24
|
-
Server.init_and_run(@config, @resources_dir)
|
31
|
+
Server.init_and_run(@config, @resources_dir, github_cache)
|
25
32
|
end
|
26
33
|
|
27
34
|
def self.from_command_line(args)
|
@@ -35,4 +42,32 @@ class Sqlui
|
|
35
42
|
|
36
43
|
Sqlui.new(args[0])
|
37
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def github_cache
|
49
|
+
return Github::Cache.new({}, logger: Sqlui.logger) unless ENV['USE_LOCAL_SAVED_FILES']
|
50
|
+
|
51
|
+
paths = Dir.glob('sql/friends/*.sql')
|
52
|
+
blobs = paths.map { |path| { 'path' => path, 'sha' => 'foo' } }
|
53
|
+
github_cache_hash = {
|
54
|
+
'https://api.github.com/repos/nicholasdower/sqlui/git/trees/master?recursive=true' =>
|
55
|
+
Github::Cache::Entry.new(
|
56
|
+
{
|
57
|
+
'sha' => 'foo',
|
58
|
+
'truncated' => false,
|
59
|
+
'tree' => blobs
|
60
|
+
}, 60 * 60 * 24 * 365
|
61
|
+
)
|
62
|
+
}
|
63
|
+
paths.each do |path|
|
64
|
+
github_cache_hash["https://api.github.com/repos/nicholasdower/sqlui/contents/#{path}?ref=foo"] =
|
65
|
+
Github::Cache::Entry.new(
|
66
|
+
{
|
67
|
+
'content' => Base64.encode64(File.read(path))
|
68
|
+
}, 60 * 60 * 24 * 365
|
69
|
+
)
|
70
|
+
end
|
71
|
+
Github::Cache.new(github_cache_hash, logger: Sqlui.logger)
|
72
|
+
end
|
38
73
|
end
|
data/app/views/databases.erb
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
border-bottom: 1px solid #ddd;
|
18
18
|
height: 36px;
|
19
19
|
font-family: Helvetica, sans-serif;
|
20
|
-
padding: 5px;
|
20
|
+
padding: 5px 0;
|
21
21
|
}
|
22
22
|
|
23
23
|
.header, .server-name {
|
@@ -30,68 +30,89 @@
|
|
30
30
|
|
31
31
|
.header {
|
32
32
|
font-weight: bold;
|
33
|
-
|
33
|
+
margin-right: 30px;
|
34
|
+
margin-left: 3px;
|
35
|
+
}
|
36
|
+
|
37
|
+
.header img {
|
38
|
+
height: 20px;
|
39
|
+
margin: 0 5px 0 5px;
|
34
40
|
}
|
35
41
|
|
36
42
|
.server-name {
|
37
43
|
flex: 1;
|
38
|
-
padding-left: 15px;
|
39
44
|
font-weight: normal;
|
45
|
+
overflow: hidden;
|
46
|
+
white-space: nowrap;
|
47
|
+
margin: 0;
|
40
48
|
}
|
41
49
|
|
42
|
-
.
|
50
|
+
.name {
|
51
|
+
font-size: 18px;
|
52
|
+
color: #333;
|
53
|
+
font-weight: bold;
|
54
|
+
padding: 0 5px;
|
43
55
|
display: flex;
|
44
56
|
flex-direction: row;
|
45
57
|
align-items: center;
|
46
|
-
|
47
|
-
}
|
48
|
-
|
49
|
-
.link {
|
50
|
-
margin-right: 30px;
|
51
|
-
color: darkblue;
|
52
|
-
font-size: 17px;
|
53
|
-
text-decoration: none;
|
54
|
-
}
|
55
|
-
|
56
|
-
.name {
|
57
|
-
margin: 0 200px 0 0;
|
58
|
-
font-size: 20px;
|
58
|
+
height: 35px
|
59
59
|
}
|
60
60
|
|
61
61
|
.description {
|
62
|
-
margin:
|
62
|
+
margin: 10px 0 0;
|
63
63
|
font-size: 18px;
|
64
|
+
padding: 5px;
|
64
65
|
}
|
65
66
|
|
66
67
|
.database {
|
67
68
|
margin: 0;
|
68
|
-
padding: 10px;
|
69
|
-
border-bottom: 1px solid #
|
69
|
+
padding: 5px 10px;
|
70
|
+
border-bottom: 1px solid #ddd;
|
71
|
+
display: block;
|
72
|
+
color: #333;
|
73
|
+
cursor: pointer;
|
74
|
+
text-decoration: none;
|
75
|
+
}
|
76
|
+
|
77
|
+
.name:focus-visible {
|
78
|
+
outline: 2px solid #333;
|
79
|
+
outline-offset: -2px;
|
70
80
|
}
|
71
81
|
|
72
82
|
.database:last-child {
|
73
83
|
border-bottom: none;
|
74
84
|
}
|
75
85
|
</style>
|
86
|
+
|
87
|
+
<script type="application/javascript">
|
88
|
+
function route(event, url) {
|
89
|
+
if (event.keyCode === 13) {
|
90
|
+
if (event.shiftKey) {
|
91
|
+
window.open(url).focus()
|
92
|
+
} else if (event.metaKey) {
|
93
|
+
window.open(url, '_blank').focus()
|
94
|
+
} else {
|
95
|
+
window.location = url
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
</script>
|
76
100
|
</head>
|
77
101
|
|
78
102
|
<body>
|
79
103
|
<div class="header-box">
|
80
|
-
<
|
81
|
-
<
|
104
|
+
<div class="header"><img src="/sqlui/favicon.svg">SQLUI</div>
|
105
|
+
<div class="server-name"><%= config.name %> Databases</div>
|
82
106
|
</div>
|
83
107
|
<% config.database_configs.each do |database_config| %>
|
84
|
-
<
|
85
|
-
<
|
86
|
-
|
87
|
-
<a class='link query-link' href="<%= "#{config.base_url_path}/#{database_config.url_path}/query" %>">query</a>
|
88
|
-
<a class='link saved-link' href="<%= "#{config.base_url_path}/#{database_config.url_path}/saved" %>">saved</a>
|
89
|
-
<a class='link structure-link' href="<%= "#{config.base_url_path}/#{database_config.url_path}/structure" %>">structure</a>
|
108
|
+
<a class='database' href='<%= "#{config.base_url_path}/#{database_config.url_path}/query" %>' tabindex="-1">
|
109
|
+
<div class='name' onkeydown='route(event, "<%= "#{config.base_url_path}/#{database_config.url_path}/query" %>")' tabindex="0">
|
110
|
+
<%= database_config.display_name %>
|
90
111
|
</div>
|
91
112
|
<p class='description'>
|
92
113
|
<%= database_config.description %>
|
93
114
|
</p>
|
94
|
-
</
|
115
|
+
</a>
|
95
116
|
<% end %>
|
96
117
|
</body>
|
97
118
|
</html>
|
data/app/views/error.erb
CHANGED
@@ -6,17 +6,25 @@
|
|
6
6
|
<title><%= title %></title>
|
7
7
|
<link rel="icon" type="image/x-icon" href="<%= resource_path_map['favicon.svg'] %>">
|
8
8
|
</head>
|
9
|
-
<body style="font-family: monospace; font-size: 16px;">
|
9
|
+
<body style="font-family: monospace; color: #333; font-size: 16px; margin: 0;">
|
10
|
+
|
11
|
+
<div style="padding: 10px;">
|
12
|
+
<% if defined?(heading) && heading %>
|
13
|
+
<h2><%= heading %></h2>
|
14
|
+
<% end %>
|
10
15
|
|
11
16
|
<% if defined?(message) && message %>
|
12
|
-
|
17
|
+
<h3>Message</h3>
|
18
|
+
<p><%= message %></p>
|
13
19
|
<% end %>
|
14
20
|
|
15
21
|
<% if defined?(stacktrace) && stacktrace %>
|
22
|
+
<h3>Stacktrace</h3>
|
16
23
|
<pre>
|
17
24
|
<%= stacktrace %>
|
18
25
|
</pre>
|
19
26
|
<% end %>
|
27
|
+
</div>
|
20
28
|
|
21
29
|
</body>
|
22
30
|
</html>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<html lang="en">
|
4
|
+
<head>
|
5
|
+
<meta charset="utf-8">
|
6
|
+
<title>SQLUI - Redirecting...</title>
|
7
|
+
<link rel="icon" type="image/x-icon" href="<%= resource_path_map['favicon.svg'] %>">
|
8
|
+
|
9
|
+
<script type="application/javascript">
|
10
|
+
window.location = "<%= location %>"
|
11
|
+
</script>
|
12
|
+
</head>
|
13
|
+
<body style="font-family: monospace; color: #333; font-size: 16px; margin: 0;">
|
14
|
+
|
15
|
+
<div style="padding: 10px;">
|
16
|
+
<h2>Redirecting...</h2>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
</body>
|
20
|
+
</html>
|
data/app/views/sqlui.erb
CHANGED
@@ -18,11 +18,14 @@
|
|
18
18
|
window.notifyAirbrake = function (error) {
|
19
19
|
window.airbrake?.notify(error)
|
20
20
|
}
|
21
|
+
|
22
|
+
window.resourcePathMap = <%= resource_path_map.to_json %>
|
21
23
|
</script>
|
22
24
|
<script type="text/javascript" src="<%= resource_path_map['sqlui.js'] %>"></script>
|
23
25
|
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
|
24
26
|
<link rel="stylesheet" href="<%= resource_path_map['sqlui.css'] %>">
|
25
27
|
<link rel="stylesheet" href="<%= resource_path_map['help.css'] %>">
|
28
|
+
<link rel="stylesheet" href="<%= resource_path_map['saved.css'] %>">
|
26
29
|
</head>
|
27
30
|
|
28
31
|
<body>
|
@@ -31,8 +34,12 @@
|
|
31
34
|
|
32
35
|
<div id="main-box" style="display:none">
|
33
36
|
<div id="tabs-box">
|
34
|
-
<
|
35
|
-
|
37
|
+
<div id="header">
|
38
|
+
<a id="header-link">
|
39
|
+
<img src="/sqlui/favicon.svg">SQLUI<span class="keyboard-shortcut-indicator">[0]</span>
|
40
|
+
</a>
|
41
|
+
</div>
|
42
|
+
<div id="server-name"></div>
|
36
43
|
<a id="query-tab-button" class="tab-button">Query<span class="keyboard-shortcut-indicator">[1]</span></a>
|
37
44
|
<a id="graph-tab-button" class="tab-button">Graph<span class="keyboard-shortcut-indicator">[2]</span></a>
|
38
45
|
<a id="saved-tab-button" class="tab-button">Saved<span class="keyboard-shortcut-indicator">[3]</span></a>
|
@@ -40,31 +47,43 @@
|
|
40
47
|
<a id="help-tab-button" class="tab-button">Help<span class="keyboard-shortcut-indicator">[5]</span></a>
|
41
48
|
</div>
|
42
49
|
|
50
|
+
<div id="filename-box" class="tab-content-element" style="display: none;">
|
51
|
+
<div id="filename"></div>
|
52
|
+
<input id="dismiss-file-button" type="button" value="dismiss">
|
53
|
+
<input id="save-file-button" type="button" value="save">
|
54
|
+
|
55
|
+
<form id="save-form" action="save-file" method="post" target="_blank">
|
56
|
+
<input id="save-form-base-sha" name="base_sha" type="hidden">
|
57
|
+
<input id="save-form-path" name="path" type="hidden">
|
58
|
+
<input id="save-form-content" name="content" type="hidden">
|
59
|
+
</form>
|
60
|
+
</div>
|
61
|
+
|
43
62
|
<div id="query-box" class="tab-content-element graph-element query-element" style="display: none;">
|
44
63
|
<div id="query" class="query"></div>
|
45
64
|
</div>
|
46
65
|
|
47
66
|
<div id="submit-box" class="tab-content-element graph-element query-element" style="display: none;">
|
48
|
-
<input id="cancel-button" type="button" value="cancel"
|
67
|
+
<input id="cancel-button" type="button" value="cancel">
|
49
68
|
<div id="editor-resizer">
|
50
69
|
<img src="<%= resource_path_map['vertical-resizer.svg'] %>" />
|
51
70
|
</div>
|
52
71
|
<div style="position: relative;">
|
53
72
|
<div id="submit-button-wrapper">
|
54
|
-
<input id="submit-button-all" class="submit-button" type="button"
|
55
|
-
<input id="submit-button-current" class="submit-button submit-button-show" type="button"
|
56
|
-
<input id="submit-dropdown-button" class="submit-dropdown-button" type="button", value="▼"
|
73
|
+
<input id="submit-button-all" class="submit-button" type="button">
|
74
|
+
<input id="submit-button-current" class="submit-button submit-button-show" type="button">
|
75
|
+
<input id="submit-dropdown-button" class="submit-dropdown-button" type="button", value="▼">
|
57
76
|
</div>
|
58
77
|
<div id="submit-dropdown-content" class="submit-dropdown-content">
|
59
78
|
<div class="submit-dropdown-content-section">
|
60
|
-
<input id="submit-dropdown-button-current" class="submit-dropdown-content-button" type="button"
|
61
|
-
<input id="submit-dropdown-button-all" class="submit-dropdown-content-button" type="button"
|
62
|
-
<input id="submit-dropdown-button-toggle" class="submit-dropdown-content-button" type="button" value="toggle default"
|
79
|
+
<input id="submit-dropdown-button-current" class="submit-dropdown-content-button" type="button">
|
80
|
+
<input id="submit-dropdown-button-all" class="submit-dropdown-content-button" type="button">
|
81
|
+
<input id="submit-dropdown-button-toggle" class="submit-dropdown-content-button" type="button" value="toggle default">
|
63
82
|
</div>
|
64
83
|
<div class="submit-dropdown-content-section">
|
65
|
-
<input id="submit-dropdown-button-copy-csv" class="submit-dropdown-content-button disabled" type="button" value="copy to clipboard (csv)"
|
66
|
-
<input id="submit-dropdown-button-copy-tsv" class="submit-dropdown-content-button disabled" type="button" value="copy to clipboard (tsv)"
|
67
|
-
<input id="submit-dropdown-button-download-csv" class="submit-dropdown-content-button disabled" type="button" value="download (csv)"
|
84
|
+
<input id="submit-dropdown-button-copy-csv" class="submit-dropdown-content-button disabled" type="button" value="copy to clipboard (csv)">
|
85
|
+
<input id="submit-dropdown-button-copy-tsv" class="submit-dropdown-content-button disabled" type="button" value="copy to clipboard (tsv)">
|
86
|
+
<input id="submit-dropdown-button-download-csv" class="submit-dropdown-content-button disabled" type="button" value="download (csv)">
|
68
87
|
</div>
|
69
88
|
</div>
|
70
89
|
</div>
|
@@ -81,7 +100,7 @@
|
|
81
100
|
<p id="result-time" class="result-time"></p>
|
82
101
|
</div>
|
83
102
|
|
84
|
-
<div id="saved-box" class="tab-content-element saved-element" style="display: none;"
|
103
|
+
<div id="saved-box" class="tab-content-element saved-element" style="display: none;">
|
85
104
|
</div>
|
86
105
|
|
87
106
|
<div id="structure-box" class="tab-content-element structure-element" style="display: none;">
|
@@ -112,6 +131,8 @@
|
|
112
131
|
<tr class="keyboard-shortcut-section"><td colspan="3">App Shortcuts</td></tr>
|
113
132
|
<tr class="keyboard-shortcut-header"><td> Mac</td><td>Windows</td><td>Action</td></tr>
|
114
133
|
<tr><td>Ctrl+0</td><td></td><td>Show databases</td></tr>
|
134
|
+
<tr><td>Ctrl+[</td><td></td><td>Select previous tab</td></tr>
|
135
|
+
<tr><td>Ctrl+]</td><td></td><td>Select next tab</td></tr>
|
115
136
|
<tr><td>Ctrl+1</td><td></td><td>Select query tab</td></tr>
|
116
137
|
<tr><td>Ctrl+2</td><td></td><td>Select graph tab</td></tr>
|
117
138
|
<tr><td>Ctrl+3</td><td></td><td>Select saved tab</td></tr>
|
@@ -1 +1,50 @@
|
|
1
|
-
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3
|
+
<svg width="32" height="32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
4
|
+
<g>
|
5
|
+
<defs>
|
6
|
+
</defs>
|
7
|
+
|
8
|
+
<g id="set0">
|
9
|
+
<path id="shape0" d=" M0.6826928 -0.058527663 C-1.8339055 7.1213145 2.286095 14.361337 3.4783902 17.410105 C6.8799577 15.381417 13.838911 10.612167 14.66118 7.3574014 C11.495465 5.2562203 7.7952757 0.22987776 0.6826928 -0.058527663 Z" fill-rule="nonzero" fill="rgb(255,188,188)" fill-opacity="1.0" />
|
10
|
+
<path id="stroke0" d=" M0.6826928 -0.058527663 L0.6826928 -0.058527663 C-1.480452 6.1129136 1.2597084 12.328817 2.8292632 15.889266 L2.8292632 15.889266 C3.0857253 16.471037 3.3109336 16.981909 3.4783902 17.410105 L3.4783902 17.410105 L3.4783902 17.410105 C6.8799577 15.381417 13.838911 10.612167 14.66118 7.3574014 L14.66118 7.3574014 L14.66118 7.3574014 C13.8889675 6.8448606 13.084953 6.158268 12.207366 5.408847 L12.207366 5.408847 C11.15299 4.5084567 9.992414 3.5173755 8.653195 2.628495 L8.653195 2.628495 C6.537447 1.2242088 3.9758277 0.075004406 0.6826928 -0.058527663 L0.6826928 -0.058527663 L0.6826928 -0.058527663 M0.6826928 -0.058527663 L0.6826928 -0.058527663 C3.9758277 0.075004406 6.537447 1.2242088 8.653195 2.628495 L8.653195 2.628495 C9.992414 3.5173755 11.15299 4.5084567 12.207366 5.408847 L12.207366 5.408847 C13.084953 6.158268 13.8889675 6.8448606 14.66118 7.3574014 L14.66118 7.3574014 C13.838911 10.612167 6.8799577 15.381417 3.4783902 17.410105 L3.4783902 17.410105 C3.3109336 16.981909 3.0857253 16.471037 2.8292632 15.889266 L2.8292632 15.889266 C1.2597084 12.328817 -1.480452 6.1129136 0.6826928 -0.058527663 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
11
|
+
</g>
|
12
|
+
<g id="set1">
|
13
|
+
<path id="shape1" d=" M31.156357 -0.02738928 C33.672955 7.152453 29.552954 14.392475 28.360659 17.441244 C24.959091 15.412556 18.000137 10.643306 17.17787 7.38854 C20.343584 5.2873588 24.043774 0.26101613 31.156357 -0.02738928 Z" fill-rule="nonzero" fill="rgb(255,188,188)" fill-opacity="1.0" />
|
14
|
+
<path id="stroke1" d=" M31.156357 -0.02738928 L31.156357 -0.02738928 C33.3195 6.1440516 30.57934 12.359956 29.009787 15.920404 L29.009787 15.920404 C28.753325 16.502174 28.528116 17.013048 28.360659 17.441244 L28.360659 17.441244 C24.959091 15.412556 18.000137 10.643306 17.17787 7.38854 L17.17787 7.38854 C17.95008 6.875999 18.754095 6.1894064 19.631683 5.4399853 L19.631683 5.4399853 C20.686058 4.539595 21.846634 3.548514 23.185854 2.6596334 L23.185854 2.6596334 C25.301601 1.2553473 27.863222 0.10614279 31.156357 -0.02738928 L31.156357 -0.02738928 M31.156357 -0.02738928 L31.156357 -0.02738928 L31.156357 -0.02738928 C27.863222 0.10614279 25.301601 1.2553473 23.185854 2.6596334 L23.185854 2.6596334 C21.846634 3.548514 20.686058 4.539595 19.631683 5.4399853 L19.631683 5.4399853 C18.754095 6.1894064 17.95008 6.875999 17.17787 7.38854 L17.17787 7.38854 L17.17787 7.38854 C18.000137 10.643306 24.959091 15.412556 28.360659 17.441244 L28.360659 17.441244 L28.360659 17.441244 C28.528116 17.013048 28.753325 16.502174 29.009787 15.920404 L29.009787 15.920404 C30.57934 12.359956 33.3195 6.1440516 31.156357 -0.02738928 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
15
|
+
</g>
|
16
|
+
<g id="set2">
|
17
|
+
<path id="shape2" d=" M2.9183166 3.4238684 C1.1940731 8.506888 4.0168853 13.632512 4.8337846 15.79091 C7.1643634 14.354685 11.93228 10.978262 12.495656 8.674027 C10.326672 7.1864815 7.7914925 3.628047 2.9183166 3.4238684 Z" fill-rule="nonzero" fill="rgb(255,86,86)" fill-opacity="1.0" />
|
18
|
+
<path id="stroke2" d=" M2.9183166 3.4238684 L2.9183166 3.4238684 C1.4362413 7.792983 3.313658 12.193576 4.389036 14.714221 L4.389036 14.714221 C4.5647507 15.126089 4.719052 15.487764 4.8337846 15.79091 L4.8337846 15.79091 L4.8337846 15.79091 C7.1643634 14.354685 11.93228 10.978262 12.495656 8.674027 L12.495656 8.674027 L12.495656 8.674027 C11.966577 8.311171 11.415707 7.8250923 10.814429 7.2945347 L10.814429 7.2945347 C10.092026 6.657097 9.296859 5.955454 8.379294 5.3261647 L8.379294 5.3261647 C6.9296927 4.3319907 5.174603 3.5184033 2.9183166 3.4238684 L2.9183166 3.4238684 L2.9183166 3.4238684 M2.9183166 3.4238684 L2.9183166 3.4238684 C5.174603 3.5184033 6.9296927 4.3319907 8.379294 5.3261647 L8.379294 5.3261647 C9.296859 5.955454 10.092026 6.657097 10.814429 7.2945347 L10.814429 7.2945347 C11.415707 7.8250923 11.966577 8.311171 12.495656 8.674027 L12.495656 8.674027 C11.93228 10.978262 7.1643634 14.354685 4.8337846 15.79091 L4.8337846 15.79091 C4.719052 15.487764 4.5647507 15.126089 4.389036 14.714221 L4.389036 14.714221 C3.313658 12.193576 1.4362413 7.792983 2.9183166 3.4238684 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
19
|
+
</g>
|
20
|
+
<g id="set3">
|
21
|
+
<path id="shape3" d=" M29.06705 3.4238684 C30.791294 8.506888 27.968483 13.632512 27.151583 15.79091 C24.821005 14.354685 20.05309 10.978262 19.489712 8.674027 C21.658697 7.1864815 24.193876 3.628047 29.06705 3.4238684 Z" fill-rule="nonzero" fill="rgb(255,86,86)" fill-opacity="1.0" />
|
22
|
+
<path id="stroke3" d=" M29.06705 3.4238684 L29.06705 3.4238684 C30.549128 7.792983 28.671711 12.193576 27.596333 14.714221 L27.596333 14.714221 C27.420618 15.126089 27.266315 15.487764 27.151583 15.79091 L27.151583 15.79091 C24.821005 14.354685 20.05309 10.978262 19.489712 8.674027 L19.489712 8.674027 C20.018791 8.311171 20.56966 7.8250923 21.170938 7.2945347 L21.170938 7.2945347 C21.893343 6.657097 22.688509 5.955454 23.606073 5.3261647 L23.606073 5.3261647 C25.055676 4.3319907 26.810764 3.5184033 29.06705 3.4238684 L29.06705 3.4238684 M29.06705 3.4238684 L29.06705 3.4238684 L29.06705 3.4238684 C26.810764 3.5184033 25.055676 4.3319907 23.606073 5.3261647 L23.606073 5.3261647 C22.688509 5.955454 21.893343 6.657097 21.170938 7.2945347 L21.170938 7.2945347 C20.56966 7.8250923 20.018791 8.311171 19.489712 8.674027 L19.489712 8.674027 L19.489712 8.674027 C20.05309 10.978262 24.821005 14.354685 27.151583 15.79091 L27.151583 15.79091 L27.151583 15.79091 C27.266315 15.487764 27.420618 15.126089 27.596333 14.714221 L27.596333 14.714221 C28.671711 12.193576 30.549128 7.792983 29.06705 3.4238684 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
23
|
+
</g>
|
24
|
+
<g id="set4">
|
25
|
+
<path id="shape4" d=" M31.432985 19.548239 C33.260033 26.515272 29.05147 31.956104 16.164059 31.956104 C3.2766519 31.956104 -0.6709142 26.629631 0.24261434 19.891314 C1.1561399 13.152998 8.23579 7.140375 16.164059 7.140375 C24.092329 7.140375 29.605942 12.581206 31.432985 19.548239 Z" fill-rule="nonzero" fill="rgb(255,188,188)" fill-opacity="1.0" />
|
26
|
+
<path id="stroke4" d=" M31.432985 19.548239 L31.432985 19.548239 C32.829685 24.874243 30.699202 29.30834 23.860678 31.101686 L23.860678 31.101686 C21.753614 31.654245 19.199589 31.956104 16.164059 31.956104 L16.164059 31.956104 L16.164059 31.956104 C4.443288 31.956104 0.11705533 27.550343 0.11705533 21.683664 L0.11705533 21.683664 C0.11705533 21.09972 0.15991692 20.501303 0.24261434 19.891314 L0.24261434 19.891314 L0.24261434 19.891314 C1.1561399 13.152998 8.23579 7.140375 16.164059 7.140375 L16.164059 7.140375 L16.164059 7.140375 C24.092329 7.140375 29.605942 12.581206 31.432985 19.548239 L31.432985 19.548239 L31.432985 19.548239 M31.432985 19.548239 L31.432985 19.548239 C29.605942 12.581206 24.092329 7.140375 16.164059 7.140375 L16.164059 7.140375 C8.23579 7.140375 1.1561399 13.152998 0.24261434 19.891314 L0.24261434 19.891314 C0.15991692 20.501303 0.11705533 21.09972 0.11705533 21.683664 L0.11705533 21.683664 C0.11705533 27.550343 4.443288 31.956104 16.164059 31.956104 L16.164059 31.956104 C19.199589 31.956104 21.753614 31.654245 23.860678 31.101686 L23.860678 31.101686 C30.699202 29.30834 32.829685 24.874243 31.432985 19.548239 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
27
|
+
</g>
|
28
|
+
<g id="set5">
|
29
|
+
<path id="shape5" d=" M22.934938 24.251135 C23.760532 20.953186 21.858795 18.377686 16.035318 18.377686 C10.211844 18.377686 8.428045 20.899052 8.840844 24.088736 C9.253642 27.278418 12.452746 30.124582 16.035318 30.124582 C19.617891 30.124582 22.109346 27.549084 22.934938 24.251135 Z" fill-rule="nonzero" fill="rgb(255,86,86)" fill-opacity="1.0" />
|
30
|
+
<path id="stroke5" d=" M22.934938 24.251135 L22.934938 24.251135 C23.57933 21.67702 22.5622 19.543028 19.315609 18.730291 L19.315609 18.730291 C18.402676 18.50175 17.313456 18.377686 16.035318 18.377686 L16.035318 18.377686 L16.035318 18.377686 C10.739017 18.377686 8.784108 20.46322 8.784108 23.2403 L8.784108 23.2403 C8.784108 23.516718 8.803475 23.799988 8.840844 24.088736 L8.840844 24.088736 C9.253642 27.278418 12.452746 30.124582 16.035318 30.124582 L16.035318 30.124582 L16.035318 30.124582 C19.617891 30.124582 22.109346 27.549084 22.934938 24.251135 L22.934938 24.251135 M22.934938 24.251135 L22.934938 24.251135 L22.934938 24.251135 C22.109346 27.549084 19.617891 30.124582 16.035318 30.124582 L16.035318 30.124582 C12.452746 30.124582 9.253642 27.278418 8.840844 24.088736 L8.840844 24.088736 L8.840844 24.088736 C8.803475 23.799988 8.784108 23.516718 8.784108 23.2403 L8.784108 23.2403 C8.784108 20.46322 10.739017 18.377686 16.035318 18.377686 L16.035318 18.377686 C17.313456 18.377686 18.402676 18.50175 19.315609 18.730291 L19.315609 18.730291 C22.5622 19.543028 23.57933 21.67702 22.934938 24.251135 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
31
|
+
</g>
|
32
|
+
<g id="set6">
|
33
|
+
<path id="shape6" d=" M11.138396 16.593264 C10.632988 17.88421 9.427752 18.619282 8.4464245 18.235092 C7.4650974 17.8509 7.0792885 16.492931 7.5846963 15.201984 C8.090104 13.911037 9.295341 13.175965 10.276668 13.560157 C11.257995 13.944347 11.643804 15.302316 11.138396 16.593264 Z" fill-rule="nonzero" fill="rgb(30,30,30)" fill-opacity="1.0" />
|
34
|
+
<path id="stroke6" d=" M11.138396 16.593264 L11.138396 16.593264 C10.632988 17.88421 9.427752 18.619282 8.4464245 18.235092 L8.4464245 18.235092 L8.4464245 18.235092 C7.4650974 17.8509 7.0792885 16.492931 7.5846963 15.201984 L7.5846963 15.201984 L7.5846963 15.201984 C8.090104 13.911037 9.295341 13.175965 10.276668 13.560157 L10.276668 13.560157 L10.276668 13.560157 C11.257995 13.944347 11.643804 15.302316 11.138396 16.593264 L11.138396 16.593264 L11.138396 16.593264 M11.138396 16.593264 L11.138396 16.593264 C11.643804 15.302316 11.257995 13.944347 10.276668 13.560157 L10.276668 13.560157 C9.295341 13.175965 8.090104 13.911037 7.5846963 15.201984 L7.5846963 15.201984 C7.0792885 16.492931 7.4650974 17.8509 8.4464245 18.235092 L8.4464245 18.235092 C9.427752 18.619282 10.632988 17.88421 11.138396 16.593264 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
35
|
+
</g>
|
36
|
+
<g id="set7">
|
37
|
+
<path id="shape7" d=" M12.219753 21.949343 L12.219753 23.743599 C12.219753 24.36315 12.678981 24.865395 13.245467 24.865395 L13.445264 24.865395 C14.01175 24.865395 14.470978 24.36315 14.470978 23.743599 L14.470978 21.949343 C14.470978 21.329792 14.01175 20.827547 13.445264 20.827547 L13.245467 20.827547 C12.678981 20.827547 12.219753 21.329792 12.219753 21.949343 Z" fill-rule="nonzero" fill="rgb(30,30,30)" fill-opacity="1.0" />
|
38
|
+
<path id="stroke7" d=" M12.219753 21.949343 L12.219753 21.949343 L12.219753 23.743599 L12.219753 23.743599 L12.219753 23.743599 C12.219753 24.36315 12.678981 24.865395 13.245467 24.865395 L13.245467 24.865395 L13.245467 24.865395 L13.445264 24.865395 L13.445264 24.865395 L13.445264 24.865395 C14.01175 24.865395 14.470978 24.36315 14.470978 23.743599 L14.470978 23.743599 L14.470978 23.743599 L14.470978 21.949343 L14.470978 21.949343 L14.470978 21.949343 C14.470978 21.329792 14.01175 20.827547 13.445264 20.827547 L13.445264 20.827547 L13.445264 20.827547 L13.245467 20.827547 L13.245467 20.827547 L13.245467 20.827547 C12.678981 20.827547 12.219753 21.329792 12.219753 21.949343 L12.219753 21.949343 L12.219753 21.949343 M12.219753 21.949343 L12.219753 21.949343 C12.219753 21.329792 12.678981 20.827547 13.245467 20.827547 L13.245467 20.827547 L13.445264 20.827547 L13.445264 20.827547 C14.01175 20.827547 14.470978 21.329792 14.470978 21.949343 L14.470978 21.949343 L14.470978 23.743599 L14.470978 23.743599 C14.470978 24.36315 14.01175 24.865395 13.445264 24.865395 L13.445264 24.865395 L13.245467 24.865395 L13.245467 24.865395 C12.678981 24.865395 12.219753 24.36315 12.219753 23.743599 L12.219753 23.743599 L12.219753 21.949343 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
39
|
+
</g>
|
40
|
+
<g id="set8">
|
41
|
+
<path id="shape8" d=" M24.518972 15.205694 C25.024378 16.496643 24.638569 17.85461 23.657242 18.2388 C22.675913 18.62299 21.470678 17.887917 20.965271 16.59697 C20.459864 15.306022 20.845675 13.948053 21.827002 13.563864 C22.808329 13.179673 24.013565 13.914746 24.518972 15.205694 Z" fill-rule="nonzero" fill="rgb(30,30,30)" fill-opacity="1.0" />
|
42
|
+
<path id="stroke8" d=" M24.518972 15.205694 L24.518972 15.205694 C25.024378 16.496643 24.638569 17.85461 23.657242 18.2388 L23.657242 18.2388 L23.657242 18.2388 C22.675913 18.62299 21.470678 17.887917 20.965271 16.59697 L20.965271 16.59697 L20.965271 16.59697 C20.459864 15.306022 20.845675 13.948053 21.827002 13.563864 L21.827002 13.563864 L21.827002 13.563864 C22.808329 13.179673 24.013565 13.914746 24.518972 15.205694 L24.518972 15.205694 L24.518972 15.205694 M24.518972 15.205694 L24.518972 15.205694 C24.013565 13.914746 22.808329 13.179673 21.827002 13.563864 L21.827002 13.563864 C20.845675 13.948053 20.459864 15.306022 20.965271 16.59697 L20.965271 16.59697 C21.470678 17.887917 22.675913 18.62299 23.657242 18.2388 L23.657242 18.2388 C24.638569 17.85461 25.024378 16.496643 24.518972 15.205694 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
43
|
+
</g>
|
44
|
+
<g id="set9">
|
45
|
+
<path id="shape9" d=" M17.340649 21.949343 L17.340649 23.743599 C17.340649 24.36315 17.799877 24.865395 18.366364 24.865395 L18.56616 24.865395 C19.132647 24.865395 19.591873 24.36315 19.591873 23.743599 L19.591873 21.949343 C19.591873 21.329792 19.132647 20.827547 18.56616 20.827547 L18.366364 20.827547 C17.799877 20.827547 17.340649 21.329792 17.340649 21.949343 Z" fill-rule="nonzero" fill="rgb(30,30,30)" fill-opacity="1.0" />
|
46
|
+
<path id="stroke9" d=" M17.340649 21.949343 L17.340649 21.949343 L17.340649 23.743599 L17.340649 23.743599 L17.340649 23.743599 C17.340649 24.36315 17.799877 24.865395 18.366364 24.865395 L18.366364 24.865395 L18.366364 24.865395 L18.56616 24.865395 L18.56616 24.865395 L18.56616 24.865395 C19.132647 24.865395 19.591873 24.36315 19.591873 23.743599 L19.591873 23.743599 L19.591873 23.743599 L19.591873 21.949343 L19.591873 21.949343 L19.591873 21.949343 C19.591873 21.329792 19.132647 20.827547 18.56616 20.827547 L18.56616 20.827547 L18.56616 20.827547 L18.366364 20.827547 L18.366364 20.827547 L18.366364 20.827547 C17.799877 20.827547 17.340649 21.329792 17.340649 21.949343 L17.340649 21.949343 L17.340649 21.949343 M17.340649 21.949343 L17.340649 21.949343 C17.340649 21.329792 17.799877 20.827547 18.366364 20.827547 L18.366364 20.827547 L18.56616 20.827547 L18.56616 20.827547 C19.132647 20.827547 19.591873 21.329792 19.591873 21.949343 L19.591873 21.949343 L19.591873 23.743599 L19.591873 23.743599 C19.591873 24.36315 19.132647 24.865395 18.56616 24.865395 L18.56616 24.865395 L18.366364 24.865395 L18.366364 24.865395 C17.799877 24.865395 17.340649 24.36315 17.340649 23.743599 L17.340649 23.743599 L17.340649 21.949343 Z" fill="rgb(0,0,0)" fill-opacity="1.0" />
|
47
|
+
</g>
|
48
|
+
|
49
|
+
</g>
|
50
|
+
</svg>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="32" viewBox="0 0 16 16" version="1.1" width="32">
|
2
|
+
<path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"></path>
|
3
|
+
</svg>
|