Signed-off-by: Joas Schilling <coding@schilljs.com>tags/v14.0.0beta1
@@ -32,6 +32,8 @@ | |||
!/apps/testing | |||
!/apps/admin_audit | |||
!/apps/updatenotification | |||
/apps/updatenotification/js/merged.js | |||
/apps/updatenotification/node_modules | |||
!/apps/theming | |||
!/apps/twofactor_backupcodes | |||
!/apps/workflowengine |
@@ -0,0 +1,47 @@ | |||
app_name=notifications | |||
project_dir=$(CURDIR)/../$(app_name) | |||
build_dir=$(CURDIR)/build | |||
source_dir=$(build_dir)/$(app_name) | |||
sign_dir=$(build_dir)/sign | |||
all: package | |||
dev-setup: clean npm-update build-js | |||
npm-update: | |||
rm -rf node_modules | |||
npm update | |||
build-js: | |||
npm run dev | |||
build-js-production: | |||
npm run build | |||
clean: | |||
rm -rf $(build_dir) | |||
package: clean build-js-production | |||
mkdir -p $(source_dir) | |||
rsync -a \ | |||
--exclude=/build \ | |||
--exclude=/docs \ | |||
--exclude=/js-src \ | |||
--exclude=/l10n/.tx \ | |||
--exclude=/tests \ | |||
--exclude=/.git \ | |||
--exclude=/.github \ | |||
--exclude=/CONTRIBUTING.md \ | |||
--exclude=/issue_template.md \ | |||
--exclude=/README.md \ | |||
--exclude=/.gitignore \ | |||
--exclude=/.scrutinizer.yml \ | |||
--exclude=/.travis.yml \ | |||
--exclude=/.drone.yml \ | |||
--exclude=/node_modules \ | |||
--exclude=/npm-debug.log \ | |||
--exclude=/package.json \ | |||
--exclude=/package-lock.json \ | |||
--exclude=/Makefile \ | |||
$(project_dir)/ $(source_dir) |
@@ -7,12 +7,12 @@ | |||
* later. See the COPYING file. | |||
*/ | |||
(function(OC, OCA, Vue, $) { | |||
"use strict"; | |||
/* global $, define */ | |||
OCA.UpdateNotification = OCA.UpdateNotification || {}; | |||
define(function (require) { | |||
"use strict"; | |||
OCA.UpdateNotification.App = { | |||
return { | |||
/** @type {number|null} */ | |||
@@ -26,7 +26,8 @@ | |||
*/ | |||
initialise: function() { | |||
var data = JSON.parse($('#updatenotification').attr('data-json')); | |||
this.vm = new Vue(OCA.UpdateNotification.Components.Root); | |||
var Vue = require('vue'); | |||
this.vm = new Vue(require('./components/root.vue')); | |||
this.vm.newVersionString = data.newVersionString; | |||
this.vm.lastCheckedDate = data.lastChecked; | |||
@@ -41,8 +42,4 @@ | |||
this.vm.isDefaultUpdateServerURL = data.isDefaultUpdateServerURL; | |||
} | |||
}; | |||
})(OC, OCA, Vue, $); | |||
$(document).ready(function () { | |||
OCA.UpdateNotification.App.initialise(); | |||
}); |
@@ -0,0 +1,188 @@ | |||
<template> | |||
<div id="updatenotification" class="followupsection"> | |||
<p> | |||
<template v-if="isNewVersionAvailable"> | |||
<strong>{{newVersionAvailableString}}</strong> | |||
<input v-if="updaterEnabled" type="button" @click="clickUpdaterButton" id="oca_updatenotification_button" :value="l_open_updater"> | |||
<a v-if="downloadLink" :href="downloadLink" class="button" :class="{ hidden: !updaterEnabled }">{{l_download_now}}</a> | |||
</template> | |||
<template v-else-if="!isUpdateChecked">{{l_check_in_progress}}</template> | |||
<template v-else> | |||
{{l_up_to_date}} | |||
<span class="icon-info svg" :title="lastCheckedOnString"></span> | |||
</template> | |||
<template v-if="!isDefaultUpdateServerURL"> | |||
<br /> | |||
<em>{{l_non_default_updater}} <code>{{updateServerURL}}</code></em> | |||
</template> | |||
</p> | |||
<p> | |||
<label for="release-channel">{{l_update_channel}}</label> | |||
<select id="release-channel" v-model="currentChannel" @change="changeReleaseChannel"> | |||
<option v-for="channel in channels" :value="channel">{{channel}}</option> | |||
</select> | |||
<span id="channel_save_msg" class="msg"></span><br /> | |||
<em>{{l_update_channel_newer}}</em><br /> | |||
<em>{{l_update_channel_delay}}</em> | |||
</p> | |||
<p id="oca_updatenotification_groups"> | |||
{{l_notify_groups}} | |||
<input name="oca_updatenotification_groups_list" type="hidden" id="oca_updatenotification_groups_list" @change="saveNotifyGroups" :value="notifyGroups" style="width: 400px"><br /> | |||
<em v-if="currentChannel === 'daily' || currentChannel === 'git'">{{l_only_app_updates}}</em> | |||
<em v-if="currentChannel === 'daily'">{{l_update_channel_daily}}</em> | |||
<em v-if="currentChannel === 'git'">{{l_update_channel_git}}</em> | |||
</p> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: "root", | |||
el: '#updatenotification', | |||
data: function () { | |||
return { | |||
newVersionString: '', | |||
lastCheckedDate: '', | |||
isUpdateChecked: false, | |||
updaterEnabled: true, | |||
downloadLink: '', | |||
isNewVersionAvailable: false, | |||
updateServerURL: '', | |||
currentChannel: '', | |||
channels: [], | |||
notifyGroups: '', | |||
isDefaultUpdateServerURL: true | |||
}; | |||
}, | |||
_$el: null, | |||
_$releaseChannel: null, | |||
_$notifyGroups: null, | |||
computed: { | |||
l_check_in_progress: function() { | |||
return t('updatenotification', 'The update check is not yet finished. Please refresh the page.'); | |||
}, | |||
l_download_now: function() { | |||
return t('updatenotification', 'Download now'); | |||
}, | |||
l_non_default_updater: function() { | |||
return t('updatenotification', 'A non-default update server is in use to be checked for updates:'); | |||
}, | |||
l_notify_groups: function() { | |||
return t('updatenotification', 'Notify members of the following groups about available updates:'); | |||
}, | |||
l_only_app_updates: function() { | |||
return t('updatenotification', 'Only notification for app updates are available.'); | |||
}, | |||
l_open_updater: function() { | |||
return t('updatenotification', 'Open updater'); | |||
}, | |||
l_up_to_date: function() { | |||
return t('updatenotification', 'Your version is up to date.'); | |||
}, | |||
l_update_channel: function() { | |||
return t('updatenotification', 'Update channel:'); | |||
}, | |||
l_update_channel_daily: function() { | |||
return t('updatenotification', 'The selected update channel makes dedicated notifications for the server obsolete.'); | |||
}, | |||
l_update_channel_git: function() { | |||
return t('updatenotification', 'The selected update channel does not support updates of the server.'); | |||
}, | |||
l_update_channel_newer: function() { | |||
return t('updatenotification', 'You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel.'); | |||
}, | |||
l_update_channel_delay: function() { | |||
return t('updatenotification', 'Note that after a new release it can take some time before it shows up here. We roll out new versions spread out over time to our users and sometimes skip a version when issues are found.'); | |||
}, | |||
newVersionAvailableString: function() { | |||
return t('updatenotification', 'A new version is available: {newVersionString}', { | |||
newVersionString: this.newVersionString | |||
}); | |||
}, | |||
lastCheckedOnString: function() { | |||
return t('updatenotification', 'Checked on {lastCheckedDate}', { | |||
lastCheckedDate: this.lastCheckedDate | |||
}); | |||
} | |||
}, | |||
methods: { | |||
/** | |||
* Creates a new authentication token and loads the updater URL | |||
*/ | |||
clickUpdaterButton: function() { | |||
$.ajax({ | |||
url: OC.generateUrl('/apps/updatenotification/credentials') | |||
}).success(function(data) { | |||
$.ajax({ | |||
url: OC.getRootPath()+'/updater/', | |||
headers: { | |||
'X-Updater-Auth': data | |||
}, | |||
method: 'POST', | |||
success: function(data){ | |||
if(data !== 'false') { | |||
var body = $('body'); | |||
$('head').remove(); | |||
body.html(data); | |||
// Eval the script elements in the response | |||
var dom = $(data); | |||
dom.filter('script').each(function() { | |||
eval(this.text || this.textContent || this.innerHTML || ''); | |||
}); | |||
body.removeAttr('id'); | |||
body.attr('id', 'body-settings'); | |||
} | |||
}, | |||
error: function() { | |||
OC.Notification.showTemporary(t('updatenotification', 'Could not start updater, please try the manual update')); | |||
this.updaterEnabled = false; | |||
}.bind(this) | |||
}); | |||
}.bind(this)); | |||
}, | |||
changeReleaseChannel: function() { | |||
this.currentChannel = this._$releaseChannel.val(); | |||
$.ajax({ | |||
url: OC.generateUrl('/apps/updatenotification/channel'), | |||
type: 'POST', | |||
data: { | |||
'channel': this.currentChannel | |||
}, | |||
success: function (data) { | |||
OC.msg.finishedAction('#channel_save_msg', data); | |||
} | |||
}); | |||
}, | |||
saveNotifyGroups: function(e) { | |||
var groups = e.val || []; | |||
groups = JSON.stringify(groups); | |||
OCP.AppConfig.setValue('updatenotification', 'notify_groups', groups); | |||
} | |||
}, | |||
mounted: function () { | |||
this._$el = $(this.$el); | |||
this._$releaseChannel = this._$el.find('#release-channel'); | |||
this._$notifyGroups = this._$el.find('#oca_updatenotification_groups_list'); | |||
this._$notifyGroups.on('change', function () { | |||
this.$emit('input'); | |||
}.bind(this)); | |||
}, | |||
updated: function () { | |||
OC.Settings.setupGroupsSelect(this._$notifyGroups); | |||
this._$el.find('.icon-info').tooltip({placement: 'right'}); | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,31 @@ | |||
/** | |||
* @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* This program 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 Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
/* global define, $ */ | |||
define(function(require) { | |||
'use strict'; | |||
var App = require('./app'); | |||
$(function() { | |||
App.initialise(); | |||
}); | |||
}); |
@@ -0,0 +1,55 @@ | |||
var path = require('path'); | |||
var webpack = require('webpack'); | |||
module.exports = { | |||
entry: './js-src/init.js', | |||
output: { | |||
path: path.resolve(__dirname, '../js'), | |||
publicPath: '/', | |||
filename: 'merged.js' | |||
}, | |||
module: { | |||
rules: [ | |||
{ | |||
test: /\.vue$/, | |||
loader: 'vue-loader', | |||
options: { | |||
loaders: { | |||
}, | |||
esModule: false | |||
// other vue-loader options go here | |||
} | |||
} | |||
] | |||
}, | |||
resolve: { | |||
alias: { | |||
'vue': process.env.NODE_ENV === 'production' ? 'vue/dist/vue.min.js' : 'vue/dist/vue.js' | |||
} | |||
}, | |||
performance: { | |||
hints: false | |||
}, | |||
devtool: '#eval-source-map' | |||
}; | |||
if (process.env.NODE_ENV === 'production') { | |||
module.exports.devtool = '#source-map'; | |||
// http://vue-loader.vuejs.org/en/workflow/production.html | |||
module.exports.plugins = (module.exports.plugins || []).concat([ | |||
new webpack.DefinePlugin({ | |||
'process.env': { | |||
NODE_ENV: '"production"' | |||
} | |||
}), | |||
new webpack.optimize.UglifyJsPlugin({ | |||
sourceMap: true, | |||
compress: { | |||
warnings: false | |||
} | |||
}), | |||
new webpack.LoaderOptionsPlugin({ | |||
minimize: true | |||
}) | |||
]); | |||
} |
@@ -1,165 +0,0 @@ | |||
/** | |||
* @copyright (c) 2018 Joas Schilling <coding@schilljs.com> | |||
* @copyright (c) 2016 ownCloud Inc | |||
* | |||
* @author Joas Schilling <coding@schilljs.com> | |||
* @author Lukas Reschke <lukas@owncloud.com> | |||
* | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. See the COPYING file. | |||
*/ | |||
(function(OC, OCA, OCP, t, $) { | |||
"use strict"; | |||
OCA.UpdateNotification = OCA.UpdateNotification || {}; | |||
OCA.UpdateNotification.Components = OCA.UpdateNotification.Components || {}; | |||
OCA.UpdateNotification.Components.Root = { | |||
template: '' + | |||
'<div id="updatenotification" class="followupsection">' + | |||
' <p>' + | |||
' <template v-if="isNewVersionAvailable">' + | |||
' <strong>{{newVersionAvailableString}}</strong>' + | |||
' <input v-if="updaterEnabled" type="button" @click="clickUpdaterButton" id="oca_updatenotification_button" value="' + t('updatenotification', 'Open updater') + '">' + | |||
' <a v-if="downloadLink" :href="downloadLink" class="button" :class="{ hidden: !updaterEnabled }">' + t('updatenotification', 'Download now') + '</a>' + | |||
' </template>' + | |||
' <template v-else-if="!isUpdateChecked">' + t('updatenotification', 'The update check is not yet finished. Please refresh the page.') + '</template>' + | |||
' <template v-else>' + | |||
' ' + t('updatenotification', 'Your version is up to date.') + '' + | |||
' <span class="icon-info svg" :title="lastCheckedOnString"></span>' + | |||
' </template>' + | |||
'' + | |||
' <template v-if="!isDefaultUpdateServerURL">' + | |||
' <br />' + | |||
' <em>' + | |||
' ' + t('updatenotification', 'A non-default update server is in use to be checked for updates:') + | |||
' <code>{{updateServerURL}}</code>' + | |||
' </em>' + | |||
' </template>' + | |||
' </p>' + | |||
'' + | |||
' <p>' + | |||
' <label for="release-channel">' + t('updatenotification', 'Update channel:') + '</label>' + | |||
' <select id="release-channel" v-model="currentChannel" @change="changeReleaseChannel">' + | |||
' <option v-for="channel in channels" :value="channel">{{channel}}</option>' + | |||
' </select>' + | |||
' <span id="channel_save_msg" class="msg"></span><br />' + | |||
' <em>' + t('updatenotification', 'You can always update to a newer version / experimental channel. But you can never downgrade to a more stable channel.') + '</em><br />' + | |||
' <em>' + t('updatenotification', 'Note that after a new release it can take some time before it shows up here. We roll out new versions spread out over time to our users and sometimes skip a version when issues are found.') + '</em>' + | |||
' </p>' + | |||
'' + | |||
' <p id="oca_updatenotification_groups">' + | |||
' ' + t('updatenotification', 'Notify members of the following groups about available updates:') + | |||
' <input name="oca_updatenotification_groups_list" type="hidden" id="oca_updatenotification_groups_list" v-model="notifyGroups" @change="saveNotifyGroups" :value="notifyGroups" style="width: 400px"><br />' + | |||
' <em v-if="currentChannel === \'daily\' || currentChannel === \'git\'">' + t('updatenotification', 'Only notification for app updates are available.') + '</em>' + | |||
' <em v-if="currentChannel === \'daily\'">' + t('updatenotification', 'The selected update channel makes dedicated notifications for the server obsolete.') + '</em>' + | |||
' <em v-if="currentChannel === \'git\'">' + t('updatenotification', 'The selected update channel does not support updates of the server.') + '</em>' + | |||
' </p>' + | |||
'</div>', | |||
el: '#updatenotification', | |||
data: { | |||
newVersionString: '', | |||
lastCheckedDate: '', | |||
isUpdateChecked: false, | |||
updaterEnabled: true, | |||
downloadLink: '', | |||
isNewVersionAvailable: false, | |||
updateServerURL: '', | |||
currentChannel: '', | |||
channels: [], | |||
notifyGroups: '', | |||
isDefaultUpdateServerURL: true | |||
}, | |||
_$el: null, | |||
_$releaseChannel: null, | |||
_$notifyGroups: null, | |||
computed: { | |||
newVersionAvailableString: function() { | |||
return t('updatenotification', 'A new version is available: {newVersionString}', { | |||
newVersionString: this.newVersionString | |||
}); | |||
}, | |||
lastCheckedOnString: function() { | |||
return t('updatenotification', 'Checked on {lastCheckedDate}', { | |||
lastCheckedDate: this.lastCheckedDate | |||
}); | |||
} | |||
}, | |||
methods: { | |||
/** | |||
* Creates a new authentication token and loads the updater URL | |||
*/ | |||
clickUpdaterButton: function() { | |||
$.ajax({ | |||
url: OC.generateUrl('/apps/updatenotification/credentials') | |||
}).success(function(data) { | |||
$.ajax({ | |||
url: OC.getRootPath()+'/updater/', | |||
headers: { | |||
'X-Updater-Auth': data | |||
}, | |||
method: 'POST', | |||
success: function(data){ | |||
if(data !== 'false') { | |||
var body = $('body'); | |||
$('head').remove(); | |||
body.html(data); | |||
// Eval the script elements in the response | |||
var dom = $(data); | |||
dom.filter('script').each(function() { | |||
eval(this.text || this.textContent || this.innerHTML || ''); | |||
}); | |||
body.removeAttr('id'); | |||
body.attr('id', 'body-settings'); | |||
} | |||
}, | |||
error: function() { | |||
OC.Notification.showTemporary(t('updatenotification', 'Could not start updater, please try the manual update')); | |||
this.updaterEnabled = false; | |||
}.bind(this) | |||
}); | |||
}.bind(this)); | |||
}, | |||
changeReleaseChannel: function() { | |||
this.currentChannel = this._$releaseChannel.val(); | |||
$.ajax({ | |||
url: OC.generateUrl('/apps/updatenotification/channel'), | |||
type: 'POST', | |||
data: { | |||
'channel': this.currentChannel | |||
}, | |||
success: function (data) { | |||
OC.msg.finishedAction('#channel_save_msg', data); | |||
} | |||
}); | |||
}, | |||
saveNotifyGroups: function(e) { | |||
var groups = e.val || []; | |||
groups = JSON.stringify(groups); | |||
OCP.AppConfig.setValue('updatenotification', 'notify_groups', groups); | |||
} | |||
}, | |||
mounted: function () { | |||
this._$el = $(this.$el); | |||
this._$releaseChannel = this._$el.find('#release-channel'); | |||
this._$notifyGroups = this._$el.find('#oca_updatenotification_groups_list'); | |||
this._$notifyGroups.on('change', function () { | |||
this.$emit('input'); | |||
}.bind(this)); | |||
}, | |||
updated: function () { | |||
OC.Settings.setupGroupsSelect(this._$notifyGroups); | |||
this._$el.find('.icon-info').tooltip({placement: 'right'}); | |||
} | |||
}; | |||
})(OC, OCA, OCP, t, $); |
@@ -0,0 +1,36 @@ | |||
{ | |||
"name": "notifications", | |||
"version": "2.2.0", | |||
"description": "This app provides a backend and frontend for the notification API available in Nextcloud.", | |||
"main": "init.js", | |||
"directories": { | |||
"lib": "lib", | |||
"test": "tests" | |||
}, | |||
"scripts": { | |||
"dev": "cross-env NODE_ENV=development webpack --progress --hot --config js-src/webpack.config.js --watch", | |||
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules --config js-src/webpack.config.js", | |||
"test": "echo \"Error: no test specified\" && exit 1" | |||
}, | |||
"repository": { | |||
"type": "git", | |||
"url": "git+https://github.com/nextcloud/notifications.git" | |||
}, | |||
"author": "Joas Schilling", | |||
"license": "AGPL-3.0", | |||
"bugs": { | |||
"url": "https://github.com/nextcloud/notifications/issues" | |||
}, | |||
"homepage": "https://github.com/nextcloud/notifications#readme", | |||
"dependencies": { | |||
"vue": "^2.5.13" | |||
}, | |||
"devDependencies": { | |||
"cross-env": "^5.1.3", | |||
"css-loader": "^0.28.8", | |||
"file-loader": "^1.1.6", | |||
"vue-loader": "^13.7.0", | |||
"vue-template-compiler": "^2.5.13", | |||
"webpack": "^3.6.0" | |||
} | |||
} |
@@ -8,15 +8,7 @@ declare(strict_types=1); | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. See the COPYING file. | |||
*/ | |||
if (\OC::$server->getConfig()->getSystemValue('debug', false)) { | |||
script('updatenotification', 'vue'); | |||
} else { | |||
script('updatenotification', 'vue.min'); | |||
} | |||
script('updatenotification', [ | |||
'components/root', | |||
'admin', | |||
]); | |||
script('updatenotification', 'merged'); | |||
style('updatenotification', 'admin'); | |||
/** @var array $_ */ | |||
?> |