Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nextcloud-app-radio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
44
Issues
44
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
onny
nextcloud-app-radio
Commits
c7d21c74
Commit
c7d21c74
authored
Nov 19, 2020
by
onny
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix dashboard widget
parent
02de2c65
Pipeline
#210
failed with stages
in 12 minutes and 10 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
63 additions
and
183 deletions
+63
-183
lib/Dashboard/RadioWidget.php
lib/Dashboard/RadioWidget.php
+10
-6
src/components/Dashboard.vue
src/components/Dashboard.vue
+19
-158
src/dashboard.js
src/dashboard.js
+12
-16
src/main.js
src/main.js
+0
-2
webpack.js
webpack.js
+22
-1
No files found.
lib/Dashboard/RadioWidget.php
View file @
c7d21c74
...
...
@@ -14,10 +14,15 @@ class RadioWidget implements IWidget {
/** @var IL10N */
private
$l10n
;
/** @var IURLGenerator */
private
$urlGenerator
;
public
function
__construct
(
IL10N
$l10n
IL10N
$l10n
,
IURLGenerator
$urlGenerator
)
{
$this
->
l10n
=
$l10n
;
$this
->
urlGenerator
=
$urlGenerator
;
}
/**
...
...
@@ -52,15 +57,14 @@ class RadioWidget implements IWidget {
* @inheritDoc
*/
public
function
getUrl
():
?string
{
return
\
OC
::
$server
->
getURLGenerator
()
->
linkToRoute
(
'radio.page.index'
);
// return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute('radio.page.index'));
return
$this
->
urlGenerator
->
getAbsoluteURL
(
$this
->
urlGenerator
->
linkToRoute
(
'radio.page.index'
));
}
/**
* @inheritDoc
*/
public
function
load
():
void
{
Util
::
addScript
(
Application
::
APP_ID
,
'
dashboard'
);
Util
::
addStyle
(
Application
::
APP_ID
,
'dashboard'
);
}
Util
::
addScript
(
Application
::
APP_ID
,
'radio-
dashboard'
);
Util
::
addStyle
(
Application
::
APP_ID
,
'dashboard'
);
}
}
src/components/Dashboard.vue
View file @
c7d21c74
...
...
@@ -9,11 +9,6 @@
:icon=
"emptyContentIcon"
>
<template
#desc
>
{{
emptyContentMessage
}}
<div
v-if=
"state === 'no-token' || state === 'error'"
class=
"connect-button"
>
<a
class=
"button"
:href=
"settingsUrl"
>
{{
t
(
'
integration_twitter
'
,
'
Connect to Twitter
'
)
}}
</a>
</div>
</
template
>
</EmptyContent>
</template>
...
...
@@ -22,9 +17,8 @@
<
script
>
import
axios
from
'
@nextcloud/axios
'
import
{
generateUrl
,
imagePath
}
from
'
@nextcloud/router
'
import
{
generateUrl
}
from
'
@nextcloud/router
'
import
{
showError
}
from
'
@nextcloud/dialogs
'
import
moment
from
'
@nextcloud/moment
'
import
{
DashboardWidget
}
from
'
@nextcloud/vue-dashboard
'
import
EmptyContent
from
'
@nextcloud/vue/dist/Components/EmptyContent
'
...
...
@@ -32,90 +26,49 @@ export default {
name
:
'
Dashboard
'
,
components
:
{
DashboardWidget
,
EmptyContent
,
DashboardWidget
,
EmptyContent
,
},
props
:
{
title
:
{
type
:
String
,
required
:
true
,
required
:
false
,
default
:
'
radio
'
,
},
},
data
()
{
return
{
notifications
:
[],
showMoreUrl
:
'
https://twitter.com/notifications
'
,
// lastDate could be computed but we want to keep the value when first notification is removed
// to avoid getting it again on next request
lastDate
:
null
,
loop
:
null
,
showMoreUrl
:
generateUrl
(
'
/apps/radio/api/favorites
'
),
state
:
'
loading
'
,
settingsUrl
:
generateUrl
(
'
/settings/user/connected-accounts#twitter_prefs
'
),
darkThemeColor
:
OCA
.
Accessibility
.
theme
===
'
dark
'
?
'
ffffff
'
:
'
000000
'
,
}
},
computed
:
{
items
()
{
// get rid of follow request counts
let
items
=
this
.
notifications
.
filter
((
n
)
=>
{
return
(
!
[
'
follow_request
'
].
includes
(
n
.
type
))
})
// if we have follow requests, show them in first
if
(
this
.
followRequestItem
&&
this
.
followRequestItem
.
number
>
0
)
{
items
.
unshift
(
this
.
followRequestItem
)
}
// then filter out unnecessary private messages
const
privMsgAuthorIds
=
[]
items
=
items
.
filter
((
n
)
=>
{
if
(
n
.
type
!==
'
message
'
)
{
return
true
}
else
if
(
privMsgAuthorIds
.
includes
(
n
.
sender_screen_name
))
{
return
false
}
else
{
privMsgAuthorIds
.
push
(
n
.
sender_screen_name
)
return
true
}
})
return
items
.
map
((
n
)
=>
{
return
this
.
notifications
.
map
((
n
)
=>
{
return
{
id
:
n
.
id
,
targetUrl
:
this
.
getNotificationTarget
(
n
),
avatarUrl
:
this
.
getUserAvatarUrl
(
n
),
avatarUsername
:
this
.
getAvatarText
(
n
),
overlayIconUrl
:
this
.
getNotificationTypeImage
(
n
),
mainText
:
this
.
getMainText
(
n
),
subText
:
this
.
getSubline
(
n
),
targetUrl
:
generateUrl
(
'
/apps/radio/api/favorites
'
),
avatarUrl
:
n
.
favicon
,
mainText
:
n
.
name
,
subText
:
n
.
tags
,
}
})
},
followRequestItem
()
{
// find the last follow request notif
return
this
.
notifications
.
find
((
n
)
=>
{
return
n
.
type
===
'
follow_request
'
})
},
lastMoment
()
{
return
moment
(
this
.
lastDate
)
},
emptyContentMessage
()
{
if
(
this
.
state
===
'
no-token
'
)
{
return
t
(
'
radio
'
,
'
No Twitter account connected
'
)
}
else
if
(
this
.
state
===
'
error
'
)
{
return
t
(
'
radio
'
,
'
Error connecting to Twitter
'
)
if
(
this
.
state
===
'
error
'
)
{
return
t
(
'
radio
'
,
'
Error fetching favorite stations
'
)
}
else
if
(
this
.
state
===
'
ok
'
)
{
return
t
(
'
radio
'
,
'
No
Twitter notifications
!
'
)
return
t
(
'
radio
'
,
'
No
favorites added yet
!
'
)
}
return
''
},
emptyContentIcon
()
{
if
(
this
.
state
===
'
no-token
'
)
{
return
'
icon-radio
'
}
else
if
(
this
.
state
===
'
error
'
)
{
if
(
this
.
state
===
'
error
'
)
{
return
'
icon-close
'
}
else
if
(
this
.
state
===
'
ok
'
)
{
return
'
icon-checkmark
'
...
...
@@ -126,29 +79,18 @@ export default {
beforeMount
()
{
this
.
fetchNotifications
()
this
.
loop
=
setInterval
(()
=>
this
.
fetchNotifications
(),
120000
)
},
mounted
()
{
},
methods
:
{
fetchNotifications
()
{
const
req
=
{}
if
(
this
.
lastDate
)
{
req
.
params
=
{
since
:
this
.
lastDate
,
}
}
axios
.
get
(
generateUrl
(
'
/apps/radio/favorites
'
),
req
).
then
((
response
)
=>
{
axios
.
get
(
generateUrl
(
'
/apps/radio/api/favorites
'
),
req
).
then
((
response
)
=>
{
this
.
processNotifications
(
response
.
data
)
this
.
state
=
'
ok
'
}).
catch
((
error
)
=>
{
clearInterval
(
this
.
loop
)
if
(
error
.
response
&&
error
.
response
.
status
===
400
)
{
this
.
state
=
'
no-token
'
}
else
if
(
error
.
response
&&
error
.
response
.
status
===
401
)
{
showError
(
t
(
'
integration_twitter
'
,
'
Failed to get Twitter notifications
'
))
if
(
error
.
response
&&
error
.
response
.
status
===
401
)
{
showError
(
t
(
'
radio
'
,
'
Failed to fetch favorite radio stations
'
))
this
.
state
=
'
error
'
}
else
{
// there was an error in notif processing
...
...
@@ -157,89 +99,8 @@ export default {
})
},
processNotifications
(
newNotifications
)
{
if
(
this
.
lastDate
)
{
// just add those which are more recent than our most recent one
let
i
=
0
while
(
i
<
newNotifications
.
length
&&
this
.
lastDate
<
newNotifications
[
i
].
timestamp
)
{
i
++
}
if
(
i
>
0
)
{
const
toAdd
=
this
.
filter
(
newNotifications
.
slice
(
0
,
i
))
this
.
notifications
=
toAdd
.
concat
(
this
.
notifications
)
}
}
else
{
// first time we don't check the date
this
.
notifications
=
this
.
filter
(
newNotifications
)
}
// update lastDate manually (explained in data)
const
nbNotif
=
this
.
notifications
.
length
this
.
lastDate
=
(
nbNotif
>
0
)
?
this
.
notifications
[
0
].
timestamp
:
null
},
filter
(
notifications
)
{
return
notifications
},
getUserAvatarUrl
(
n
)
{
return
(
n
.
profile_image_url_https
&&
n
.
sender_id_str
)
?
generateUrl
(
'
/apps/integration_twitter/avatar?
'
)
+
encodeURIComponent
(
'
userId
'
)
+
'
=
'
+
encodeURIComponent
(
n
.
sender_id_str
)
:
n
.
type
===
'
follow_request
'
?
imagePath
(
'
integration_twitter
'
,
'
twitter.png
'
)
:
''
},
getAvatarText
(
n
)
{
if
([
'
follow_request
'
].
includes
(
n
.
type
))
{
return
'
!
'
}
return
''
},
getNotificationTarget
(
n
)
{
if
([
'
retweet
'
,
'
mention
'
].
includes
(
n
.
type
))
{
return
'
https://twitter.com/
'
+
n
.
sender_screen_name
+
'
/status/
'
+
n
.
id_str
}
else
if
([
'
message
'
].
includes
(
n
.
type
))
{
return
'
https://twitter.com/messages
'
}
else
if
([
'
follow_request
'
].
includes
(
n
.
type
))
{
return
'
https://twitter.com/follower_requests
'
}
return
''
},
getMainText
(
n
)
{
if
([
'
follow_request
'
].
includes
(
n
.
type
))
{
return
t
(
'
integration_twitter
'
,
'
{nb} follow requests
'
,
{
nb
:
n
.
number
})
}
else
if
([
'
retweet
'
,
'
mention
'
].
includes
(
n
.
type
))
{
let
text
=
n
.
text
while
(
text
.
startsWith
(
'
@
'
))
{
text
=
text
.
replace
(
/^@
[^\s]
*
\s?
/
,
''
)
}
return
text
}
return
n
.
text
},
getSubline
(
n
)
{
if
([
'
follow_request
'
].
includes
(
n
.
type
))
{
return
t
(
'
integration_twitter
'
,
'
System
'
)
}
return
'
@
'
+
n
.
sender_screen_name
},
getNotificationTypeImage
(
n
)
{
if
(
n
.
type
===
'
mention
'
)
{
return
generateUrl
(
'
/svg/integration_twitter/arobase?color=ffffff
'
)
}
else
if
(
n
.
type
===
'
message
'
)
{
return
generateUrl
(
'
/svg/integration_twitter/message?color=ffffff
'
)
}
else
if
(
n
.
type
===
'
retweet
'
)
{
return
generateUrl
(
'
/svg/integration_twitter/retweet?color=ffffff
'
)
}
else
if
(
n
.
type
===
'
follow_request
'
)
{
return
generateUrl
(
'
/svg/integration_twitter/follow_request?color=ffffff
'
)
}
return
''
},
getFormattedDate
(
n
)
{
return
moment
(
n
.
timestamp
).
format
(
'
LLL
'
)
this
.
notifications
=
newNotifications
},
},
}
</
script
>
<
style
scoped
lang=
"scss"
>
::v-deep
.connect-button
{
margin-top
:
10px
;
}
</
style
>
src/dashboard.js
View file @
c7d21c74
import
Vue
from
'
vue
'
import
{
translate
,
translatePlural
}
from
'
@nextcloud/l10n
'
import
Dashboard
from
'
./components/Dashboard
'
Vue
.
prototype
.
t
=
translate
Vue
.
prototype
.
n
=
translatePlural
Vue
.
prototype
.
OC
=
window
.
OC
Vue
.
prototype
.
OCA
=
window
.
OCA
document
.
addEventListener
(
'
DOMContentLoaded
'
,
function
()
{
OCA
.
Dashboard
.
register
(
'
radio
'
,
(
el
,
{
widget
})
=>
{
const
View
=
Vue
.
extend
(
Dashboard
)
new
View
({
propsData
:
{
title
:
widget
.
title
},
}).
$mount
(
el
)
import
router
from
'
./router
'
import
store
from
'
./store
'
import
Dashboard
from
'
./components/Dashboard.vue
'
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
OCA
.
Dashboard
.
register
(
'
radio
'
,
(
el
)
=>
{
global
.
Radio
=
new
Vue
({
el
,
store
,
router
,
render
:
h
=>
h
(
Dashboard
),
})
})
})
src/main.js
View file @
c7d21c74
...
...
@@ -27,8 +27,6 @@ import { translate, translatePlural } from '@nextcloud/l10n'
import
App
from
'
./App
'
import
'
./dashboard
'
import
VueBlurHash
from
'
vue-blurhash
'
import
'
vue-blurhash/dist/vue-blurhash.css
'
...
...
webpack.js
View file @
c7d21c74
const
{
merge
}
=
require
(
'
webpack-merge
'
)
const
path
=
require
(
'
path
'
)
const
webpackConfig
=
require
(
'
@nextcloud/webpack-vue-config
'
)
module
.
exports
=
webpackConfig
const
config
=
{
entry
:
{
dashboard
:
path
.
join
(
__dirname
,
'
src
'
,
'
dashboard.js
'
),
},
module
:
{
rules
:
[
{
test
:
/
\.
vue$/
,
loader
:
'
vue-loader
'
,
},
],
},
}
const
mergedConfigs
=
merge
(
config
,
webpackConfig
)
// Remove duplicate rules by the `test` key
mergedConfigs
.
module
.
rules
=
mergedConfigs
.
module
.
rules
.
filter
((
v
,
i
,
a
)
=>
a
.
findIndex
(
t
=>
(
t
.
test
.
toString
()
===
v
.
test
.
toString
()))
===
i
)
module
.
exports
=
mergedConfigs
Write
Preview
Markdown
is supported
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