Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
open-source
SemWeb
libview
Commits
54b9dcfe1422
Commit
ef955c2d
authored
Jul 17, 2018
by
Laurent Wouters
Browse files
Fixed issue
#2
- forced selection of a data source
parent
dba67c4a8bcf
Changes
10
Hide whitespace changes
Inline
Side-by-side
src/background/main.ts
View file @
54b9dcfe
...
@@ -66,7 +66,7 @@ function updateTab(tabId: number): void {
...
@@ -66,7 +66,7 @@ function updateTab(tabId: number): void {
function
updateIcon
(
tabId
:
number
):
void
{
function
updateIcon
(
tabId
:
number
):
void
{
let
data
=
getTabData
(
tabId
);
let
data
=
getTabData
(
tabId
);
chrome
.
browserAction
.
setIcon
({
chrome
.
browserAction
.
setIcon
({
path
:
data
.
isActive
path
:
data
.
command
.
isActive
?
{
?
{
48
:
"
icons/app.png
"
48
:
"
icons/app.png
"
}
}
...
@@ -80,7 +80,7 @@ function updateIcon(tabId: number): void {
...
@@ -80,7 +80,7 @@ function updateIcon(tabId: number): void {
tabId
:
tabId
tabId
:
tabId
});
});
chrome
.
browserAction
.
setBadgeText
({
chrome
.
browserAction
.
setBadgeText
({
text
:
data
.
mainSource
.
name
,
text
:
data
.
mainSource
==
NO_DATA
?
""
:
"
\
u2605
"
,
tabId
:
tabId
tabId
:
tabId
});
});
}
}
...
@@ -91,7 +91,7 @@ function updateIcon(tabId: number): void {
...
@@ -91,7 +91,7 @@ function updateIcon(tabId: number): void {
*/
*/
function
toggleActive
(
tab
:
chrome
.
tabs
.
Tab
):
void
{
function
toggleActive
(
tab
:
chrome
.
tabs
.
Tab
):
void
{
let
data
=
getTabData
(
tab
.
id
);
let
data
=
getTabData
(
tab
.
id
);
data
.
isActive
=
!
data
.
isActive
;
data
.
command
.
isActive
=
!
data
.
command
.
isActive
;
updateTab
(
tab
.
id
);
updateTab
(
tab
.
id
);
}
}
...
@@ -270,7 +270,7 @@ function doPreempt(
...
@@ -270,7 +270,7 @@ function doPreempt(
setHeader
(
headers
,
"
Content-Type
"
,
"
text/plain
"
);
setHeader
(
headers
,
"
Content-Type
"
,
"
text/plain
"
);
let
data
=
getTabData
(
details
.
tabId
);
let
data
=
getTabData
(
details
.
tabId
);
data
.
sources
.
push
(
new
DataSourcePage
(
details
.
url
,
mime
.
mime
));
data
.
sources
.
push
(
new
DataSourcePage
(
details
.
url
,
mime
.
mime
));
data
.
isActive
=
true
;
// activate by default
data
.
command
.
isActive
=
true
;
// activate by default
data
.
selectMain
();
data
.
selectMain
();
return
{
responseHeaders
:
headers
};
return
{
responseHeaders
:
headers
};
}
}
...
@@ -359,13 +359,20 @@ chrome.webRequest.onHeadersReceived.addListener(
...
@@ -359,13 +359,20 @@ chrome.webRequest.onHeadersReceived.addListener(
F
.
registerNavigations
(
onBeforeNavigate
,
onCompleted
);
F
.
registerNavigations
(
onBeforeNavigate
,
onCompleted
);
chrome
.
runtime
.
onMessage
.
addListener
((
request
,
sender
,
sendResponse
)
=>
{
chrome
.
runtime
.
onMessage
.
addListener
((
request
,
sender
,
sendResponse
)
=>
{
let
data
=
getTabData
(
sender
.
tab
.
id
);
if
(
request
.
reqType
==
"
links
"
)
{
if
(
request
.
reqType
==
"
links
"
)
{
let
data
=
getTabData
(
sender
.
tab
.
id
);
if
(
data
.
primaryTopic
==
null
)
{
if
(
data
.
primaryTopic
==
null
)
{
data
.
primaryTopic
=
detectTopicOnlinks
(
request
.
links
);
data
.
primaryTopic
=
detectTopicOnlinks
(
request
.
links
);
}
}
data
.
sources
=
data
.
sources
.
concat
(
detectDataOnLinks
(
request
.
links
));
data
.
sources
=
data
.
sources
.
concat
(
detectDataOnLinks
(
request
.
links
));
data
.
selectMain
();
data
.
selectMain
();
updateTab
(
sender
.
tab
.
id
);
updateTab
(
sender
.
tab
.
id
);
}
else
if
(
request
.
reqType
==
"
GetTabData
"
)
{
let
data
=
getTabData
(
request
.
tabId
);
sendResponse
(
data
);
}
else
if
(
request
.
reqType
==
"
UpdateTabData
"
)
{
let
data
=
getTabData
(
request
.
tabId
);
data
.
updateWith
(
request
.
tabData
);
updateTab
(
request
.
tabId
);
}
}
});
});
src/common/data.ts
View file @
54b9dcfe
...
@@ -168,7 +168,7 @@ export interface DataSource {
...
@@ -168,7 +168,7 @@ export interface DataSource {
export
class
DataSourceNone
implements
DataSource
{
export
class
DataSourceNone
implements
DataSource
{
constructor
()
{
constructor
()
{
this
.
sourceType
=
"
DataSourceNone
"
;
this
.
sourceType
=
"
DataSourceNone
"
;
this
.
name
=
""
;
this
.
name
=
"
No data
"
;
this
.
url
=
""
;
this
.
url
=
""
;
this
.
contentType
=
""
;
this
.
contentType
=
""
;
this
.
priority
=
Number
.
MAX_SAFE_INTEGER
;
this
.
priority
=
Number
.
MAX_SAFE_INTEGER
;
...
@@ -185,8 +185,11 @@ export class DataSourceNone implements DataSource {
...
@@ -185,8 +185,11 @@ export class DataSourceNone implements DataSource {
*/
*/
export
class
DataSourcePage
implements
DataSource
{
export
class
DataSourcePage
implements
DataSource
{
constructor
(
url
:
string
,
contentType
:
string
)
{
constructor
(
url
:
string
,
contentType
:
string
)
{
let
mime
=
MIME
[
contentType
];
this
.
sourceType
=
"
DataSourcePage
"
;
this
.
sourceType
=
"
DataSourcePage
"
;
this
.
name
=
"
*
"
;
this
.
name
=
"
Page's content
"
+
(
mime
!=
undefined
&&
mime
!=
null
?
"
(
"
+
mime
.
name
+
"
)
"
:
""
);
this
.
url
=
url
;
this
.
url
=
url
;
this
.
contentType
=
contentType
;
this
.
contentType
=
contentType
;
this
.
priority
=
1
;
this
.
priority
=
1
;
...
@@ -232,7 +235,12 @@ export class DataSourceLinked implements DataSource {
...
@@ -232,7 +235,12 @@ export class DataSourceLinked implements DataSource {
if
(
mime
==
null
||
mime
==
undefined
)
throw
"
Unrecognized link type
"
;
if
(
mime
==
null
||
mime
==
undefined
)
throw
"
Unrecognized link type
"
;
this
.
tags
=
link
.
tags
;
this
.
tags
=
link
.
tags
;
this
.
sourceType
=
"
DataSourceLinked
"
;
this
.
sourceType
=
"
DataSourceLinked
"
;
this
.
name
=
mime
.
name
;
this
.
name
=
"
Linked content
"
+
(
mime
!=
undefined
&&
mime
!=
null
?
"
(
"
+
mime
.
name
+
"
)
"
:
""
)
+
"
(
"
+
link
.
url
+
"
)
"
;
this
.
url
=
link
.
url
;
this
.
url
=
link
.
url
;
this
.
contentType
=
mime
.
mime
;
this
.
contentType
=
mime
.
mime
;
this
.
priority
=
mime
.
priority
;
this
.
priority
=
mime
.
priority
;
...
@@ -302,23 +310,60 @@ function compareSources(x: DataSource, y: DataSource): number {
...
@@ -302,23 +310,60 @@ function compareSources(x: DataSource, y: DataSource): number {
*/
*/
export
const
NO_DATA
=
new
DataSourceNone
();
export
const
NO_DATA
=
new
DataSourceNone
();
/**
* The user command for a tab
*/
export
class
TabCommand
{
constructor
()
{
this
.
isActive
=
false
;
this
.
isAutomatic
=
true
;
this
.
selectedSource
=
null
;
this
.
selectedView
=
null
;
}
/**
* Whether the user activated the extension for this tab
*/
isActive
:
boolean
;
/**
* Whether the user is using automatic selection of data sources and views
*/
isAutomatic
:
boolean
;
/**
* The identifier of the selected data source (if not automatic)
*/
selectedSource
:
string
;
/**
* The identifier of the selected view (if not automatic)
*/
selectedView
:
string
;
/**
* Updates this command with the specified one
* @param command The updated command
*/
updateWith
(
command
:
TabCommand
)
{
this
.
isActive
=
command
.
isActive
;
this
.
isAutomatic
=
command
.
isAutomatic
;
this
.
selectedSource
=
command
.
selectedSource
;
this
.
selectedView
=
command
.
selectedView
;
}
}
/**
/**
* Data about a tab
* Data about a tab
*/
*/
export
class
TabData
{
export
class
TabData
{
constructor
()
{
constructor
()
{
this
.
isActive
=
false
;
this
.
command
=
new
TabCommand
()
;
this
.
mainSource
=
NO_DATA
;
this
.
mainSource
=
NO_DATA
;
this
.
sources
=
[];
this
.
sources
=
[];
//this.clear = this.clear.bind(this);
this
.
primaryTopic
=
null
;
this
.
primaryTopic
=
null
;
//this.selectMain = this.selectMain.bind(this);
}
}
/**
/**
*
Whether the user activated the extension
for this tab
*
The user command
for this tab
*/
*/
isActive
:
boole
an
;
command
:
TabComm
an
d
;
/**
/**
* The data associated to this tab
* The data associated to this tab
*/
*/
...
@@ -332,10 +377,22 @@ export class TabData {
...
@@ -332,10 +377,22 @@ export class TabData {
*/
*/
primaryTopic
:
string
;
primaryTopic
:
string
;
/**
* Updates this data with the specified one
* @param data The updated data
*/
updateWith
(
data
:
TabData
)
{
this
.
command
.
updateWith
(
data
.
command
);
this
.
selectMain
();
}
/**
/**
* Clears this data
* Clears this data
*/
*/
clear
():
void
{
clear
():
void
{
this
.
command
.
isAutomatic
=
true
;
this
.
command
.
selectedSource
=
null
;
this
.
command
.
selectedView
=
null
;
this
.
mainSource
=
NO_DATA
;
this
.
mainSource
=
NO_DATA
;
this
.
sources
=
[];
this
.
sources
=
[];
this
.
primaryTopic
=
null
;
this
.
primaryTopic
=
null
;
...
@@ -345,15 +402,27 @@ export class TabData {
...
@@ -345,15 +402,27 @@ export class TabData {
* Selects the main resource among the provided one
* Selects the main resource among the provided one
*/
*/
selectMain
():
DataSource
{
selectMain
():
DataSource
{
if
(
this
.
sources
.
length
==
0
)
{
if
(
this
.
command
.
isAutomatic
||
this
.
command
.
selectedSource
==
null
)
{
this
.
mainSource
=
NO_DATA
;
if
(
this
.
sources
.
length
==
0
)
{
this
.
mainSource
=
NO_DATA
;
}
else
{
this
.
sources
=
this
.
sources
.
filter
((
source
:
DataSource
)
=>
{
return
source
!=
NO_DATA
;
})
.
sort
(
compareSources
);
this
.
mainSource
=
this
.
sources
.
length
==
0
?
NO_DATA
:
this
.
sources
[
0
];
}
}
else
{
}
else
{
this
.
sources
=
this
.
sources
this
.
mainSource
=
this
.
sources
.
reduce
(
.
filter
((
source
:
DataSource
)
=>
{
(
acc
:
DataSource
,
current
:
DataSource
)
=>
{
return
source
!=
NO_DATA
;
if
(
acc
!=
null
)
return
acc
;
})
if
(
current
.
url
==
this
.
command
.
selectedSource
)
return
current
;
.
sort
(
compareSources
);
return
null
;
this
.
mainSource
=
this
.
sources
.
length
==
0
?
NO_DATA
:
this
.
sources
[
0
];
},
null
);
if
(
this
.
mainSource
==
null
)
this
.
mainSource
=
NO_DATA
;
}
}
return
this
.
mainSource
;
return
this
.
mainSource
;
}
}
...
...
src/common/rdf.ts
View file @
54b9dcfe
...
@@ -27,7 +27,7 @@ let _rdf = require("rdflib");
...
@@ -27,7 +27,7 @@ let _rdf = require("rdflib");
export
const
$rdf
:
RDF
=
_rdf
;
export
const
$rdf
:
RDF
=
_rdf
;
export
function
loadRdfStore
(
tabData
:
TabData
):
Promise
<
any
>
{
export
function
loadRdfStore
(
tabData
:
TabData
):
Promise
<
any
>
{
if
(
!
tabData
.
isActive
)
{
if
(
!
tabData
.
command
.
isActive
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
reject
(
"
no data
"
);
reject
(
"
no data
"
);
});
});
...
...
src/content/main.ts
View file @
54b9dcfe
...
@@ -52,7 +52,7 @@ chrome.runtime.onMessage.addListener(function(
...
@@ -52,7 +52,7 @@ chrome.runtime.onMessage.addListener(function(
sender
,
sender
,
sendResponse
sendResponse
)
{
)
{
let
activate
=
request
.
isActive
&&
request
.
mainSource
!=
NO_DATA
;
let
activate
=
request
.
command
.
isActive
&&
request
.
mainSource
!=
NO_DATA
;
if
(
activate
)
onUpdateActivate
(
request
);
if
(
activate
)
onUpdateActivate
(
request
);
else
onUpdateDeactivate
();
else
onUpdateDeactivate
();
});
});
...
...
src/manifest.json
View file @
54b9dcfe
...
@@ -14,8 +14,10 @@
...
@@ -14,8 +14,10 @@
"*://*/*"
"*://*/*"
],
],
"browser_action"
:
{
"browser_action"
:
{
"browser_style"
:
true
,
"default_icon"
:
"icons/app_disabled.png"
,
"default_icon"
:
"icons/app_disabled.png"
,
"default_title"
:
"Linked Data Browser"
"default_title"
:
"Linked Data Browser"
,
"default_popup"
:
"popup/index.html"
},
},
"content_scripts"
:
[
"content_scripts"
:
[
{
{
...
...
src/popup/Menu.tsx
0 → 100644
View file @
54b9dcfe
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import
*
as
React
from
"
react
"
;
import
{
TabData
,
DataSource
,
NO_DATA
}
from
"
../common/data
"
;
import
"
chrome
"
;
import
{
stat
}
from
"
fs
"
;
export
class
Menu
extends
React
.
Component
{
state
:
TabData
;
tabId
:
number
;
constructor
(
props
:
any
)
{
super
(
props
);
this
.
state
=
new
TabData
();
this
.
onClickActivate
=
this
.
onClickActivate
.
bind
(
this
);
this
.
onClickAutomatic
=
this
.
onClickAutomatic
.
bind
(
this
);
this
.
onSelectSource
=
this
.
onSelectSource
.
bind
(
this
);
this
.
onSelectedView
=
this
.
onSelectedView
.
bind
(
this
);
let
self
=
this
;
chrome
.
tabs
.
query
(
{
active
:
true
,
currentWindow
:
true
},
(
tabs
:
chrome
.
tabs
.
Tab
[])
=>
{
self
.
tabId
=
tabs
[
0
].
id
;
chrome
.
runtime
.
sendMessage
(
{
reqType
:
"
GetTabData
"
,
tabId
:
tabs
[
0
].
id
},
(
response
:
TabData
)
=>
{
self
.
setState
(
response
);
}
);
}
);
}
onClickActivate
(
event
:
React
.
FormEvent
<
HTMLInputElement
>
)
{
this
.
state
.
command
.
isActive
=
event
.
currentTarget
.
checked
;
this
.
setState
(
this
.
state
);
chrome
.
runtime
.
sendMessage
({
reqType
:
"
UpdateTabData
"
,
tabId
:
this
.
tabId
,
tabData
:
this
.
state
});
}
onClickAutomatic
(
event
:
React
.
FormEvent
<
HTMLInputElement
>
)
{
this
.
state
.
command
.
isAutomatic
=
event
.
currentTarget
.
checked
;
if
(
this
.
state
.
command
.
isAutomatic
)
{
this
.
state
.
command
.
selectedSource
=
null
;
this
.
state
.
command
.
selectedView
==
null
;
}
this
.
setState
(
this
.
state
);
chrome
.
runtime
.
sendMessage
({
reqType
:
"
UpdateTabData
"
,
tabId
:
this
.
tabId
,
tabData
:
this
.
state
});
}
onSelectSource
(
event
:
React
.
FormEvent
<
HTMLSelectElement
>
)
{
this
.
state
.
command
.
selectedSource
=
event
.
currentTarget
.
value
;
if
(
this
.
state
.
command
.
isAutomatic
)
{
this
.
state
.
command
.
selectedSource
=
null
;
this
.
state
.
command
.
selectedView
==
null
;
}
this
.
setState
(
this
.
state
);
chrome
.
runtime
.
sendMessage
({
reqType
:
"
UpdateTabData
"
,
tabId
:
this
.
tabId
,
tabData
:
this
.
state
});
}
onSelectedView
(
event
:
React
.
FormEvent
<
HTMLSelectElement
>
)
{}
render
()
{
return
(
<
div
className
=
"container-fluid"
>
<
div
className
=
"row"
>
<
div
className
=
"col-sm-4"
>
<
label
>
Active
</
label
>
</
div
>
<
div
className
=
"col-sm-8"
>
<
label
className
=
"switch"
>
<
input
type
=
"checkbox"
id
=
"fieldActive"
checked
=
{
this
.
state
.
command
.
isActive
}
onChange
=
{
this
.
onClickActivate
}
/>
<
span
className
=
"slider round"
/>
</
label
>
</
div
>
</
div
>
<
div
className
=
"row"
>
<
div
className
=
"col-sm-4"
>
<
label
>
Auto config
</
label
>
</
div
>
<
div
className
=
"col-sm-8"
>
<
label
className
=
"switch"
>
<
input
type
=
"checkbox"
id
=
"fiedAuto"
checked
=
{
this
.
state
.
command
.
isAutomatic
}
onChange
=
{
this
.
onClickAutomatic
}
/>
<
span
className
=
"slider round"
/>
</
label
>
</
div
>
</
div
>
<
div
className
=
"row"
>
<
div
className
=
"col-sm-4"
>
<
label
>
Data source
</
label
>
</
div
>
<
div
className
=
"col-sm-8"
>
<
select
className
=
"form-control"
id
=
"fieldDataSource"
disabled
=
{
this
.
state
.
command
.
isAutomatic
}
style
=
{
{
marginTop
:
"
10pt;
"
}
}
onChange
=
{
this
.
onSelectSource
}
value
=
{
this
.
state
.
command
.
selectedSource
}
>
{
this
.
state
.
sources
.
filter
((
source
:
DataSource
)
=>
source
!=
NO_DATA
)
.
map
((
source
:
DataSource
,
index
:
number
)
=>
(
<
option
key
=
{
"
source
"
+
index
}
value
=
{
source
.
url
}
>
{
source
.
name
}
</
option
>
))
}
</
select
>
</
div
>
</
div
>
<
div
className
=
"row"
>
<
div
className
=
"col-sm-4"
>
<
label
>
View
</
label
>
</
div
>
<
div
className
=
"col-sm-8"
>
<
select
className
=
"form-control"
id
=
"fiedView"
disabled
=
{
this
.
state
.
command
.
isAutomatic
}
style
=
{
{
marginTop
:
"
10pt;
"
}
}
onChange
=
{
this
.
onSelectedView
}
value
=
{
this
.
state
.
command
.
selectedView
}
/>
</
div
>
</
div
>
</
div
>
);
}
}
src/popup/index.html
0 → 100644
View file @
54b9dcfe
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"UTF-8"
>
<meta
name=
"description"
content=
""
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1"
>
<link
rel=
"stylesheet"
href=
"bootstrap.min.css"
>
<link
rel=
"stylesheet"
href=
"main.css"
>
<title>
Linked Data Browser
</title>
</head>
<body>
<div
id=
"root"
></div>
<script
type=
"text/javascript"
src=
"bootstrap.min.js"
></script>
<script
type=
"text/javascript"
src=
"main.js"
></script></body>
</html>
\ No newline at end of file
src/popup/main.css
0 → 100644
View file @
54b9dcfe
#root
{
width
:
500pt
;
margin
:
10pt
;
}
/* The switch - the box around the slider */
.switch
{
position
:
relative
;
display
:
inline-block
;
width
:
60px
;
height
:
34px
;
}
/* Hide default HTML checkbox */
.switch
input
{
display
:
none
;
}
/* The slider */
.slider
{
position
:
absolute
;
cursor
:
pointer
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
background-color
:
#ccc
;
-webkit-transition
:
0.4s
;
transition
:
0.4s
;
}
.slider
:before
{
position
:
absolute
;
content
:
""
;
height
:
26px
;
width
:
26px
;
left
:
4px
;
bottom
:
4px
;
background-color
:
white
;
-webkit-transition
:
0.4s
;
transition
:
0.4s
;
}
input
:checked
+
.slider
{
background-color
:
#2196f3
;
}
input
:focus
+
.slider
{
box-shadow
:
0
0
1px
#2196f3
;
}
input
:checked
+
.slider
:before
{
-webkit-transform
:
translateX
(
26px
);
-ms-transform
:
translateX
(
26px
);
transform
:
translateX
(
26px
);
}
/* Rounded sliders */
.slider.round
{
border-radius
:
34px
;
}
.slider.round
:before
{
border-radius
:
50%
;
}
src/popup/main.tsx
0 → 100644
View file @
54b9dcfe
/*******************************************************************************
* Copyright 2003-2018 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
*
* This file is part of CubicWeb.
*
* CubicWeb is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 2.1 of the License, or (at your option)
* any later version.
*
* CubicWeb is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import
React
=
require
(
"
react
"
);
import
ReactDOM
=
require
(
"
react-dom
"
);
import
{
Menu
}
from
"
./Menu
"
;
ReactDOM
.
render
(<
Menu
/>,
document
.
getElementById
(
"
root
"
));
webpack.config.js
View file @
54b9dcfe