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
ad35ffef24ff
Commit
230f763f
authored
Oct 25, 2018
by
Laurent Wouters
Browse files
[feature] Implementing options page for the extension
parent
13041f9d9c47
Changes
5
Hide whitespace changes
Inline
Side-by-side
extension/src/manifest.json
View file @
ad35ffef
...
...
@@ -28,6 +28,10 @@
"background"
:
{
"scripts"
:
[
"background/main.js"
]
},
"options_ui"
:
{
"page"
:
"options/index.html"
,
"browser_style"
:
true
},
"web_accessible_resources"
:
[
"ldviews/*"
,
"ldbrowser/*"
,
"popup/*"
],
"content_security_policy"
:
"script-src 'self' 'unsafe-eval'; object-src 'self'"
}
extension/src/options/index.html
0 → 100644
View file @
ad35ffef
<!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
extension/src/options/main.css
0 → 100644
View file @
ad35ffef
#root
{
width
:
400pt
;
margin
:
10pt
;
font-size
:
12pt
;
}
select
,
option
,
input
{
font-size
:
10pt
;
}
/* The switch - the box around the slider */
.switch
{
position
:
relative
;
display
:
inline-block
;
width
:
30px
;
height
:
17px
;
}
/* 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
:
13px
;
width
:
13px
;
left
:
2px
;
bottom
:
2px
;
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
(
13px
);
-ms-transform
:
translateX
(
13px
);
transform
:
translateX
(
13px
);
}
/* Rounded sliders */
.slider.round
{
border-radius
:
17px
;
}
.slider.round
:before
{
border-radius
:
50%
;
}
extension/src/options/main.tsx
0 → 100644
View file @
ad35ffef
/*******************************************************************************
* 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
{
definition
}
from
"
@logilab/libview
"
;
import
{
getViewRegistry
,
reloadViewRegistry
,
addViewSource
,
removeViewSource
}
from
"
../common/messages
"
;
interface
State
{
pane
:
string
;
registry
:
definition
.
ViewRegistry
;
registryNewSourceName
:
string
;
registryNewSourceURI
:
string
;
showViews
:
boolean
;
}
class
Popup
extends
React
.
Component
<
{},
State
>
{
state
:
State
;
constructor
(
props
:
any
)
{
super
(
props
);
this
.
state
=
{
pane
:
"
loading
"
,
registry
:
null
,
registryNewSourceName
:
""
,
registryNewSourceURI
:
""
,
showViews
:
true
};
this
.
onButtonReloadRegistry
=
this
.
onButtonReloadRegistry
.
bind
(
this
);
this
.
onPaneSources
=
this
.
onPaneSources
.
bind
(
this
);
this
.
onPaneViews
=
this
.
onPaneViews
.
bind
(
this
);
this
.
onRegistryUpdateNewSourceName
=
this
.
onRegistryUpdateNewSourceName
.
bind
(
this
);
this
.
onRegistryUpdateNewSourceUri
=
this
.
onRegistryUpdateNewSourceUri
.
bind
(
this
);
this
.
onRegistryAddSource
=
this
.
onRegistryAddSource
.
bind
(
this
);
this
.
onRegistryRemoveSource
=
this
.
onRegistryRemoveSource
.
bind
(
this
);
this
.
renderLoading
=
this
.
renderLoading
.
bind
(
this
);
this
.
renderSources
=
this
.
renderSources
.
bind
(
this
);
this
.
renderViews
=
this
.
renderViews
.
bind
(
this
);
let
self
=
this
;
getViewRegistry
().
then
((
registry
:
definition
.
ViewRegistry
)
=>
{
self
.
state
.
pane
=
"
tab
"
;
self
.
state
.
registry
=
registry
;
self
.
setState
(
self
.
state
);
});
}
onButtonReloadRegistry
()
{
let
self
=
this
;
reloadViewRegistry
().
then
((
registry
:
definition
.
ViewRegistry
)
=>
{
self
.
state
.
registry
=
registry
;
self
.
setState
(
self
.
state
);
});
}
onPaneSources
()
{
this
.
state
.
pane
=
"
sources
"
;
this
.
setState
(
this
.
state
);
}
onPaneViews
()
{
this
.
state
.
pane
=
"
views
"
;
this
.
setState
(
this
.
state
);
}
onRegistryUpdateNewSourceName
(
event
:
React
.
FormEvent
<
HTMLInputElement
>
)
{
this
.
state
.
registryNewSourceName
=
event
.
currentTarget
.
value
;
this
.
setState
(
this
.
state
);
}
onRegistryUpdateNewSourceUri
(
event
:
React
.
FormEvent
<
HTMLInputElement
>
)
{
this
.
state
.
registryNewSourceURI
=
event
.
currentTarget
.
value
;
this
.
setState
(
this
.
state
);
}
onRegistryAddSource
()
{
let
newSource
:
definition
.
ViewRegistrySourceRemote
=
{
kind
:
definition
.
ViewRegistrySourceKind
.
remote
,
name
:
this
.
state
.
registryNewSourceName
,
uri
:
this
.
state
.
registryNewSourceURI
};
let
self
=
this
;
addViewSource
(
newSource
).
then
((
registry
:
definition
.
ViewRegistry
)
=>
{
self
.
state
.
registry
=
registry
;
self
.
state
.
registryNewSourceName
=
""
;
self
.
state
.
registryNewSourceURI
=
""
;
self
.
setState
(
self
.
state
);
});
}
onRegistryRemoveSource
(
index
:
number
)
{
let
self
=
this
;
removeViewSource
(
index
).
then
((
registry
:
definition
.
ViewRegistry
)
=>
{
self
.
state
.
registry
=
registry
;
self
.
state
.
registryNewSourceName
=
""
;
self
.
state
.
registryNewSourceURI
=
""
;
self
.
setState
(
self
.
state
);
});
}
render
()
{
if
(
this
.
state
.
pane
==
"
loading
"
)
{
return
this
.
renderLoading
();
}
else
if
(
this
.
state
.
pane
==
"
sources
"
)
{
return
this
.
renderSources
();
}
else
if
(
this
.
state
.
pane
==
"
views
"
)
{
return
this
.
renderViews
();
}
}
renderLoading
()
{
return
(
<
div
style
=
{
{
width
:
"
90%
"
,
marginLeft
:
"
5%
"
,
marginTop
:
"
5vh
"
,
marginBottom
:
"
5vh
"
}
}
>
<
div
className
=
"alert alert-info"
role
=
"alert"
>
Loading
</
div
>
</
div
>
);
}
renderSources
()
{
return
(
<
div
className
=
"container-fluid"
>
<
div
className
=
"row"
>
<
div
className
=
"col-2"
>
<
a
className
=
"btn btn-outline-light"
onClick
=
{
this
.
onPaneViews
}
title
=
"Available views"
>
<
span
style
=
{
{
fontSize
:
"
20pt
"
,
cursor
:
"
pointer
"
}
}
>
<
img
width
=
"24px"
src
=
"../icons/view.svg"
/>
</
span
>
</
a
>
</
div
>
<
div
className
=
"col-2"
>
<
a
className
=
"btn btn-outline-light"
onClick
=
{
this
.
onButtonReloadRegistry
}
title
=
"Reload registry"
>
<
span
style
=
{
{
fontSize
:
"
20pt
"
,
cursor
:
"
pointer
"
}
}
>
<
img
width
=
"24px"
src
=
"../icons/refresh.svg"
/>
</
span
>
</
a
>
</
div
>
<
div
className
=
"col-2"
/>
<
div
className
=
"col-6"
>
<
span
style
=
{
{
fontSize
:
"
17pt
"
}
}
>
Registered sources
</
span
>
</
div
>
</
div
>
<
hr
/>
<
div
className
=
"row"
>
<
div
className
=
"col-4"
>
New source name:
</
div
>
<
div
className
=
"col-8"
>
<
input
className
=
"form-control"
onChange
=
{
this
.
onRegistryUpdateNewSourceName
}
value
=
{
this
.
state
.
registryNewSourceName
}
/>
</
div
>
</
div
>
<
div
className
=
"row"
>
<
div
className
=
"col-4"
>
New source URI:
</
div
>
<
div
className
=
"col-8"
>
<
input
className
=
"form-control"
onChange
=
{
this
.
onRegistryUpdateNewSourceUri
}
value
=
{
this
.
state
.
registryNewSourceURI
}
/>
</
div
>
</
div
>
<
div
className
=
"row"
>
<
div
className
=
"col-4"
/>
<
div
className
=
"col-8"
>
<
a
className
=
"btn btn-primary"
onClick
=
{
this
.
onRegistryAddSource
}
>
OK
</
a
>
</
div
>
</
div
>
<
hr
/>
{
this
.
state
.
registry
.
sources
.
map
(
(
source
:
definition
.
ViewRegistrySource
,
index
:
number
)
=>
{
return
(
<
div
className
=
"row"
key
=
{
"
source-
"
+
index
}
>
<
div
className
=
"col-2"
>
{
source
.
kind
!=
definition
.
ViewRegistrySourceKind
.
inline
?
(
<
a
className
=
"btn btn-outline-light"
title
=
"Remove this source"
>
<
span
onClick
=
{
()
=>
this
.
onRegistryRemoveSource
(
index
)
}
style
=
{
{
cursor
:
"
pointer
"
}
}
className
=
"text-danger"
>
{
"
\
u2716
"
}
</
span
>
</
a
>
)
:
(
<
span
/>
)
}
</
div
>
<
div
className
=
"col-10"
>
<
span
>
{
source
.
name
}
</
span
>
{
source
.
kind
==
definition
.
ViewRegistrySourceKind
.
remote
?
(
<
span
>
{
"
:
"
}
<
a
href
=
{
(
source
as
definition
.
ViewRegistrySourceRemote
).
uri
}
>
{
(
source
as
definition
.
ViewRegistrySourceRemote
).
uri
}
</
a
>
</
span
>
)
:
(
<
span
/>
)
}
</
div
>
</
div
>
);
}
)
}
</
div
>
);
}
renderViews
()
{
return
(
<
div
className
=
"container-fluid"
>
<
div
className
=
"row"
>
<
div
className
=
"col-2"
>
<
a
className
=
"btn btn-outline-light"
onClick
=
{
this
.
onPaneSources
}
title
=
"Back"
>
<
span
style
=
{
{
fontSize
:
"
20pt
"
,
cursor
:
"
pointer
"
}
}
>
<
img
width
=
"24px"
src
=
"../icons/back.svg"
/>
</
span
>
</
a
>
</
div
>
<
div
className
=
"col-2"
>
<
a
className
=
"btn btn-outline-light"
onClick
=
{
this
.
onButtonReloadRegistry
}
title
=
"Reload registry"
>
<
span
style
=
{
{
fontSize
:
"
20pt
"
,
cursor
:
"
pointer
"
}
}
>
<
img
width
=
"24px"
src
=
"../icons/refresh.svg"
/>
</
span
>
</
a
>
</
div
>
<
div
className
=
"col-2"
/>
<
div
className
=
"col-6"
>
<
span
style
=
{
{
fontSize
:
"
17pt
"
}
}
>
Available views
</
span
>
</
div
>
</
div
>
<
hr
/>
{
Object
.
keys
(
this
.
state
.
registry
.
descriptors
)
.
map
((
key
:
string
)
=>
this
.
state
.
registry
.
descriptors
[
key
])
.
sort
(
(
a
:
definition
.
ViewDescriptor
,
b
:
definition
.
ViewDescriptor
):
number
=>
a
.
identifier
.
localeCompare
(
b
.
identifier
)
)
.
map
((
descriptor
:
definition
.
ViewDescriptor
,
index
:
number
)
=>
{
return
(
<
div
key
=
{
"
descriptor-
"
+
index
}
className
=
"row"
>
<
div
className
=
"col-6"
>
<
span
title
=
{
descriptor
.
description
}
>
{
descriptor
.
identifier
}
</
span
>
</
div
>
<
div
className
=
"col-6"
>
<
span
title
=
{
descriptor
.
description
}
>
{
descriptor
.
name
}
</
span
>
</
div
>
</
div
>
);
})
}
</
div
>
);
}
}
ReactDOM
.
render
(<
Popup
/>,
document
.
getElementById
(
"
root
"
));
extension/webpack.config.js
View file @
ad35ffef
...
...
@@ -170,5 +170,47 @@ module.exports = [
{}
)
]
},
{
entry
:
"
./src/options/main.tsx
"
,
mode
:
isProd
?
"
production
"
:
"
development
"
,
output
:
{
path
:
path
.
join
(
__dirname
,
"
build/
"
),
publicPath
:
path
.
join
(
__dirname
,
"
build/options/
"
),
filename
:
"
options/main.js
"
},
externals
:
{
chrome
:
"
chrome
"
},
devtool
:
"
source-map
"
,
resolve
:
{
extensions
:
[
"
.ts
"
,
"
.tsx
"
,
"
.js
"
,
"
.json
"
]
},
module
:
{
rules
:
[
{
test
:
/
\.
tsx
?
$/
,
loader
:
"
awesome-typescript-loader
"
},
{
enforce
:
"
pre
"
,
test
:
/
\.
js$/
,
loader
:
"
source-map-loader
"
}
]
},
plugins
:
[
new
CopyWebpackPlugin
(
[
{
from
:
"
src/options/index.html
"
,
to
:
"
options/index.html
"
},
{
from
:
"
src/options/main.css
"
,
to
:
"
options/main.css
"
},
{
from
:
"
node_modules/bootstrap/dist/css/bootstrap.min.css
"
,
to
:
"
options/bootstrap.min.css
"
},
{
from
:
"
node_modules/bootstrap/dist/js/bootstrap.min.js
"
,
to
:
"
options/bootstrap.min.js
"
}
],
{}
)
]
}
];
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment