Index: umc/python/updater/de.po =================================================================== --- umc/python/updater/de.po (Revision 44882) +++ umc/python/updater/de.po (Arbeitskopie) @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: univention-management-console-module-updater\n" "Report-Msgid-Bugs-To: packages@univention.de\n" -"POT-Creation-Date: 2012-11-05 09:45+0100\n" +"POT-Creation-Date: 2013-10-01 19:26+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -12,28 +12,32 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: umc/python/updater/__init__.py:108 +#: umc/python/updater/__init__.py:107 msgid "Install all available updates for the current release" msgstr "Alle verfügbaren Aktualisierungen installieren" -#: umc/python/updater/__init__.py:101 +#: umc/python/updater/__init__.py:100 msgid "Install all package updates" msgstr "Alle Paket-Aktualisierungen installieren" -#: umc/python/updater/__init__.py:95 +#: umc/python/updater/__init__.py:94 #, python-format msgid "Perform release update up to version '%s'" msgstr "Release auf Version '%s' aktualisieren" -#: umc/python/updater/__init__.py:705 +#: umc/python/updater/__init__.py:920 msgid "Unknown" msgstr "Unbekannt" -#: umc/python/updater/__init__.py:275 +#: umc/python/updater/__init__.py:250 +msgid "Updating system" +msgstr "Aktualisierung des Systems" + +#: umc/python/updater/__init__.py:512 msgid "latest version" msgstr "neueste Version" -#: umc/python/updater/__init__.py:382 +#: umc/python/updater/__init__.py:645 msgid "unknown" msgstr "unbekannt" Index: umc/python/updater/__init__.py =================================================================== --- umc/python/updater/__init__.py (Revision 44882) +++ umc/python/updater/__init__.py (Arbeitskopie) @@ -39,19 +39,18 @@ import univention.config_registry import re -from os import stat, getpid +from os import stat, getpid, path, SEEK_END from time import time from subprocess import Popen from hashlib import md5 from copy import deepcopy import univention.hooks import notifier.threads - from univention.management.console.log import MODULE from univention.management.console.protocol.definitions import * - from univention.updater import UniventionUpdater + _ = umc.Translation('univention-management-console-module-updater').translate # Base UCR path definitions @@ -112,6 +111,7 @@ } } + class Watched_File(object): """ A class that takes a file name and watches changes to this file. We don't use any advanced technologies (FAM, inotify etc.) but @@ -169,6 +169,235 @@ return self._last_returned_stamp +class Progress(object): + """Class to get the progress of updates according + to the log file (/var/log/univention/updater.log). + Output is stored in a dict to be polled by a progress bar + in auto mode + """ + + + + def __init__(self, versions, numPackageTotal): + self._logVersions = versions + self.numPackageTotal = numPackageTotal + self._steps = 0 + self._iPackage = 0 + self._addPackages = True + self._ipercent = 0 + self._logPackageLines = [] + self._countDownloadedPackages = False + self._istep = 0 + self._logFinalVersion = [] + self._logCurrentVersion = [] + self._percentOutput = 0 + self._didRunBefore = False + self._logLineOriginal = '' + self._updateFinished = False + self._updateErrors = [] + self._updateErrorCritical = False + + def startMonitoring(self,logSize1,job): + """ main function of class Progress + looks for changes in log size. If size is different + starts processing of log and returns new log size""" + + + if not self._didRunBefore: + # ----------- DEBUG ----------------- + MODULE.info("Percent is running") + MODULE.info("Packages so far: %d "%self.numPackageTotal) + MODULE.info(" %s " %self._logVersions) + # ----------------------------------- + self._didRunBefore = True + self.job = job + filename = '/var/log/univention/updater.log' + logSize2 = int(path.getsize(filename)) + if logSize2 <= logSize1: + return (logSize2) + with open(filename) as fd: + fd.seek((logSize1-logSize2),SEEK_END) + self.processNewLines(fd.readlines()) + self.poll(); + return logSize2 + + def poll(self): + """ polling function to feed an automated progress bar + refurbishes the data just like our little progress bar likes it """ + + regStatus = re.compile(r"status=(?P\w+)") + if not self.job: + self._updateErrorCritical = True + self._updateFinished = True + else: + with open(INSTALLERS[self.job]['statusfile']) as s: + lines = s.readlines() + for line in lines: + line = line.lower() + matchStatus = regStatus.match(line) + if matchStatus: + if matchStatus.group("state") == 'failed': + self._updateErrorCritical = True + self._updateFinished = True + if matchStatus.group("state") == 'success': + self._updateFinished = True + @property + def values(self): + return dict( + finished=self._updateFinished, + steps=self._percentOutput, + component=_('Updating system'), + info=self._logLineOriginal, + errors=self._updateErrors, + critical=self._updateErrorCritical + ) + + + def processNewLines(self, newlines): + """Read unprocessed lines from log file and process them.""" + for line in newlines: + self._logLineOriginal = line + line = line.lower() + # any line with 'error:' at the beginning will be collected for error handling + if line.startswith('error:'): + self._updateErrors.append(self._logLineOriginal) + MODULE.error(" WARNING: %s "%self._logLineOriginal) + if not self.numPackageTotal: + self.preDistUpgrade(line) + else: + self.countPackages(line) + + if self._logFinalVersion: + self.findCurrentVersion(line) + + # safety-switch so only the right 'Get:'s are counted + if not self._countDownloadedPackages: + if line.startswith('need to get') or line.startswith('after this operation'): + self._countDownloadedPackages = True + + + + def findCurrentVersion(self, line): + """ in case of a dist-upgrade find the current version """ + regCurrVers = re.compile(r"version=(?P[0-9.]+).*") + regCurrPatch = re.compile(r"patchlevel=(?P[0-9]*).*") + matchCurrVers = regCurrVers.match(line) + if matchCurrVers: + self._logCurrentVersion = [] + self._logCurrentVersion.append(matchCurrVers.group("currVersion")) + + # ----------- DEBUG ----------------- + MODULE.info(" Found Version= %s " %self._logCurrentVersion) + # ----------------------------------- + + matchCurrPatch = regCurrPatch.match(line) + if matchCurrPatch: + MODULE.info (" Found Patchlevel= %s " %matchCurrPatch.group("currPatch")) + self._logCurrentVersion.append('-') + self._logCurrentVersion.append(matchCurrPatch.group("currPatch")) + self._logCurrentVersion = ''.join(self._logCurrentVersion) + + # ----------- DEBUG ----------------- + MODULE.info(" Current Version : %s " %self._logCurrentVersion) + # ----------------------------------- + + #end if Current Version = Final Version + if self._logCurrentVersion == self._logFinalVersion : + MODULE.info (' trigger update finished ') + self._percentOutput = 100 + self._updateFinished = True + self.numPackageTotal = 0 + else : + # else reset counter between upgrade-steps + + # ----------- DEBUG ----------------- + MODULE.info (" Resetting counter ") + # ----------------------------------- + + self.numPackageTotal = 0 + self._countDownloadedPackages = False + if self._ipercent: + self._istep += 1 + self._iPackage = 0 + + + def increaseProgress(self): + """ calculating % """ + self._iPackage += 0.33 + p = 100.0 * self._iPackage / self.numPackageTotal + if not self._steps: + self._steps = 1 + self._ipercent = p / self._steps + + # ----------- DEBUG ----------------- + MODULE.info(" %.2f "%self.totalProgress) + # ----------------------------------- + + self._percentOutput = ("%.2f" %self.totalProgress) + + @property + def totalProgress(self): + return self._istep * (100.0 / self._steps) + self._ipercent + + def countPackages(self, line): + """ count the number of already downloaded / unpacked and progressed packages """ + regSettingUpOrUnpacking = re.compile(r"^(setting up|unpacking) .* \.\.\.\s*$") + if line.startswith('get:') and self._countDownloadedPackages: + self.increaseProgress() + if regSettingUpOrUnpacking.match(line): + self.increaseProgress() + + if line.startswith('the update has been finished'): + MODULE.info(' trigger update finished ') + self._percentOutput = 100 + self._updateFinished = True + self.numPackageTotal = 0 + + + def preDistUpgrade(self, line): + """ getting the version to wich is upgraded so we can get + the number of neccessary steps""" + regStartUpdater = re.compile(r"\*\*\*\* starting univention-updater with parameter.*--updateto', '(?P[0-9.-]+)'.*") + if not self._logFinalVersion: + matchStartUpdater = regStartUpdater.match(line) + if matchStartUpdater: + self._logFinalVersion = matchStartUpdater.group("finalVersion") + + # ----------- DEBUG ----------------- + MODULE.info(" Final Version found: %s " %self._logFinalVersion) + # ----------------------------------- + + if not self._steps: + self._steps = len(self._logVersions[0:(self._logVersions.index(self._logFinalVersion)+1)]) + # if not available get number of packages to be progressed + self.percDistUpgrade(line) + + + + def percDistUpgrade(self, line): + """ in case no package number is gathered from pre-update procedures + this function counts the number of packages to be installed / updated """ + if line.startswith('the following packages will be removed'): + self._addPackages = False + elif line.startswith('the following new packages will be installed') or line.startswith('the following packages will be upgraded'): + self._addPackages = True + elif line.startswith(' ') and self._addPackages: + self._logPackageLines.append(line) + elif line.startswith('after this operation'): + packageStr = (''.join(self._logPackageLines)).strip() + r = re.compile(r"\s+") + packages = r.split(packageStr) + self.numPackageTotal = len(packages) + self._logPackageLines = [] + + # ----------- DEBUG ----------------- + MODULE.info(" Packages: %d "%self.numPackageTotal) + # ----------------------------------- + + # +1 imaginary package so the progress won't 'rest' at 100% + self.numPackageTotal += 1 + + class Watched_Files(object): """ Convenience class to monitor more than one file at a time. """ @@ -211,8 +440,16 @@ def __init__( self ): umcm.Base.__init__( self ) + self.numPackageTotal = 0 + self._logVersions = [] + self.progress = None + self.init_called = False + # get initial log size early so we don't miss any lines + self.last_log_size = int(path.getsize('/var/log/univention/updater.log')) + self.ori_log_size = self.last_log_size + def init(self): try: if self.init_called: @@ -230,7 +467,6 @@ self._serial_file = Watched_File(COMPONENTS_SERIAL_FILE) self._updates_serial = Watched_Files(UPDATE_SERIAL_FILES) - except Exception, ex: MODULE.error("init() ERROR: %s" % str(ex)) @@ -286,7 +522,7 @@ for s in st: MODULE.info(" >> %s" % s) # ----------------------------------- - + self.finished(request.id,result) def _check_thread_error( self, thread, result, request ): @@ -307,7 +543,33 @@ return self.finished( request.id, result ) + def parseprogressresult(self, request): + """Returns current updater progress """ + #defined earlier, this is 'just in case' + if not self.last_log_size: + self.last_log_size = int(path.getsize('/var/log/univention/updater.log')) + if not self.progress: + self._logVersions = self.uu.get_all_available_release_updates()[0] + self.progress = Progress(self._logVersions, self.numPackageTotal) + + (self.last_log_size) = self.progress.startMonitoring(self.last_log_size,self.__which_job_is_running()) + result = self.progress.values + if result: + if self.progress.values['finished']: + self.progress = None + + # ----------- DEBUG ----------------- + MODULE.info("### updater/updates/parseprogress returns %s ###") + pp = pprint.PrettyPrinter(indent=4) + st = pp.pformat(result).split("\n") + for s in st: + MODULE.info("### >> %s" % s) + #------------------------------------ + + self.finished( request.id, result ) + + def call_hooks(self, request): """ Calls the specified hooks and returns data given back by each hook """ @@ -390,9 +652,18 @@ result['install'] = sorted(result['install']) result['remove'] = sorted(result['remove']) + # get number of packages + numPackageUpdated = len(result['update']) + numPackageInstalled = len(result['install']) + + self.numPackageTotal = numPackageUpdated + numPackageInstalled + # add 1 imaginary packet so progress won't rest at 100 % because of post update scripts + self.numPackageTotal = self.numPackageTotal + 1 + self.finished(request.id,result) + def updates_available(self,request): """ Asks if there are package updates available. (don't get confused by the name of the UniventionUpdater function that is called here.) @@ -581,69 +852,12 @@ self.finished(request.id, result) def updater_log_file(self,request): - """ returns the content of the log file associated with - the job. - Argument 'count' has the same meaning as already known: - <0 ...... return timestamp of file (for polling) - 0 ....... return whole file as a string list - >0 ...... ignore this many lines, return the rest of the file - - *** NOTE *** As soon as we have looked for a running job at least once, - we know the job key and can associate it here. - - TODO: honor a given 'job' argument - """ - # ----------- DEBUG ----------------- - MODULE.info("updater/installer/logfile invoked with:") - pp = pprint.PrettyPrinter(indent=4) - st = pp.pformat(request.options).split("\n") - for s in st: - MODULE.info(" << %s" % s) - # ----------------------------------- - result = None - job = '' - if self._current_job and 'job' in self._current_job: - job = self._current_job['job'] - else: - job = request.options.get('job','') - - count = request.options.get('count',0) - if count < 0: - result = 0 - else: - result = [] - if not job in INSTALLERS: - # job empty: this is the first call I can't avoid - if job != '': - MODULE.warn(" ?? Don't know a '%s' job" % job) - else: - if not 'logfile' in INSTALLERS[job]: - MODULE.warn(" ?? Job '%s' has no associated log file" % job) - else: - fname = INSTALLERS[job]['logfile'] - if count < 0: - result = self._logstamp(fname) - else: - # don't read complete file if we have an 'ignore' count - if ('lines' in self._current_job) and (self._current_job['lines']): - count += int(self._current_job['lines']) - result = self._logview(fname, -count) - - # again debug, shortened - if isinstance(result,int): - MODULE.info(" >> %d" % result) - else: - MODULE.info(" >> %d lines" % len(result)) - - # ----------- DEBUG ----------------- - MODULE.info("updater/installer/logfile returns:") - pp = pprint.PrettyPrinter(indent=4) - st = pp.pformat(result).split("\n") - for s in st: - MODULE.info(" >> %s" % s) - # ----------------------------------- - + #open log file + filename = '/var/log/univention/updater.log' + with open(filename) as fd: + result = fd.readlines() + self.finished(request.id, result) @@ -695,7 +909,7 @@ if inst == '': result['running'] = False else: - # no job running but status for release was asked? + # no job running but status for release was asked? # maybe the server restarted after job finished # and the frontend did not get that information # Bug #26318 @@ -924,7 +1138,7 @@ ''' % (started,detail,logfile,lines,command,command) p1 = subprocess.Popen( [ 'LC_ALL=C at now', ], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True ) (stdout,stderr) = p1.communicate( script ) - + if p1.returncode != 0: return (p1.returncode,stderr) else: @@ -967,4 +1181,3 @@ self._current_job[var] = val return inst return '' - Index: umc/de.mo =================================================================== Kann nicht anzeigen: Dateityp ist als binär angegeben. svn:mime-type = application/octet-stream Index: umc/updater.xml =================================================================== --- umc/updater.xml (Revision 44882) +++ umc/updater.xml (Arbeitskopie) @@ -41,5 +41,9 @@ + + + + Index: umc/de.po =================================================================== --- umc/de.po (Revision 44882) +++ umc/de.po (Arbeitskopie) @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: univention-management-console-module-updater\n" "Report-Msgid-Bugs-To: packages@univention.de\n" -"POT-Creation-Date: Tue, 30 Aug 2011 23:10:28 +0200\n" +"POT-Creation-Date: Fri, 13 Sep 2013 04:17:09 +0200\n" "PO-Revision-Date: \n" "Last-Translator: Univention GmbH \n" "Language-Team: Univention GmbH \n" @@ -17,3 +17,4 @@ msgid "Software update" msgstr "Software-Aktualisierung" + Index: umc/js/updater.js =================================================================== --- umc/js/updater.js (Revision 44882) +++ umc/js/updater.js (Arbeitskopie) @@ -34,12 +34,15 @@ "dojo/_base/array", "dijit/Dialog", "umc/dialog", + "umc/tools", "umc/widgets/ConfirmDialog", "umc/widgets/Module", "umc/modules/updater/UpdatesPage", - "umc/modules/updater/ProgressPage", + "umc/widgets/ProgressBar", + "umc/modules/updater/LogPage", + "umc/modules/lib/server", "umc/i18n!umc/modules/updater" -], function(declare, lang, array, Dialog, dialog, ConfirmDialog, Module, UpdatesPage, ProgressPage, _) { +], function(declare, lang, array, Dialog, dialog, tools, ConfirmDialog, Module, UpdatesPage, ProgressBar, LogPage, libServer, _) { return declare("umc.modules.updater", Module, { // some variables related to error handling @@ -49,6 +52,8 @@ _busy_dialog: null, // a handle to the 'connection lost' dialog while // queries return with errors. _error_count: 0, // how much errors in one row + + _reboot_required: null, buildRendering: function() { @@ -60,29 +65,18 @@ standby: lang.hitch(this, 'standby'), standbyDuring: lang.hitch(this, 'standbyDuring') }); - this._progress = new ProgressPage({}); + + this._progressBar = new ProgressBar; + this.own(this._progressBar); + this._log = new LogPage; + this.addChild(this._updates); - this.addChild(this._progress); + this.addChild(this._log); + // -------------------------------------------------------------------------- // - // Connections that make the UI work (mostly tab switching) - // - - this._progress.on('stopwatching', lang.hitch(this, function() { - // Revert to the 'Updates' page if the installer action encountered - // the 'reboot' affordance. - this.selectChild(this._updates); - })); - - // waits for the Progress Page to notify us that a job is running - this._progress.on('jobstarted', lang.hitch(this, function() { - this._switch_to_progress_page(); - })); - - // -------------------------------------------------------------------------- - // // Connections that listen for changes and propagate // them to other pages // @@ -140,8 +134,26 @@ // propagate the status information to other pages this._updates.on('statusloaded', lang.hitch(this, function(vals) { - this._progress.updateStatus(vals); + this._updateStatus(vals); })); + + // open Log when triggered + this._updates.on('clicklog', lang.hitch(this, function() { + //read log every time button is clicked + this._log._fetch_log(); + this.selectChild(this._log); + })); + + // change view back to updates page (hide log) + this._log.on('closelog', lang.hitch(this, function() { + this.selectChild(this._updates); + })); + + // shows progress bar if module is loaded while update is running in background + this._updates.on('progressresume', lang.hitch(this, function() { + this.standby(false); + this._query_progress(); + })); }, // We defer these actions until the UI is readily rendered @@ -152,7 +164,26 @@ this.selectChild(this._updates); }, + + _updateStatus: function(values) { + this._reboot_required = tools.isTrue(values.reboot_required); + }, + _ask_for_reboot: function() { + if (this._reboot_required) { + // show an alert + dialog.alert(_('In order to complete the recently executed action, it is required to reboot the system.')) + } else { + // ask user to restart + libServer.askRestart(_('For the changes to take effect, it is recommended to perform a restart of the UMC server components.')).then( + function() { /* nothing to do */ }, + function() { /* nothing at all */} + ); + } + + }, + + // Seperate function that can be called the same way as _call_installer: // instead of presenting the usual confirm dialog it presents the list // of packages for a distupgrade. @@ -347,7 +378,7 @@ this.standby(false); if (data.result.status === 0) { - this._switch_to_progress_page(); + this._query_progress(); } else { @@ -358,28 +389,12 @@ // (popup or login prompt) is well suited for the situation, so we don't disable it. lang.hitch(this, function() { this.standby(false); - })); + }) + ); }, - // Switches to the progress view: all tabs but the 'update in progess' will disappear. - // Remembers the currently selected tab and will restore it when finished. - // NOTE that we don't pass any args to the progress page since it is able - // to fetch them all from the AT job. - _switch_to_progress_page: function() { - try - { - this.selectChild(this._progress); - - this._progress.startWatching(); - } - catch(error) - { - console.error("switch_progress: " + error.message); - } - }, - // We must establish a NO ERROR callback too, so we can reset // the error status handleQuerySuccess: function(subject) { @@ -390,6 +405,30 @@ this._reset_error_status(); } }, + // invokes a progress bar which automagically polls the updater script + // for current progress and stops if finished or errors occur + _query_progress: function() { + this.standby(true, this._progressBar); + this._progressBar.reset(_('Starting the update process...')); + this._progressBar.auto( + 'updater/installer/parseprogress', + {}, + lang.hitch(this, function() { + this.standby(false); + var errors = this._progressBar.getErrors(); + if (errors.critical) { + // in case of errors notify user + dialog.alert((_('An error has occurred :') + '
' + '
' + errors.errors[0] + '
'+ '
' + _('See the log for further info !')),_('Update error')); + } else { + dialog.notify(_('The update process was successful.')); + this._ask_for_reboot(); + } + }), + undefined, + undefined, + true // let our callback handle errors + ); + }, // Recover after any kind of long-term failure: // @@ -410,6 +449,7 @@ } }, + // Handles gracefully all things related to fatal query errors while // an installer call is running. The background is that all polling // queries are done with 'handleErrors=false', and their corresponding @@ -446,11 +486,8 @@ // is already active. this._updates.refreshPage(); this._updates.startPolling(); - this._progress.startPolling(); - }) - ); + })); - dialog.notify(_("Your current session has expired, or the connection to the server was lost. You must authenticate yourself again.")); } // else Index: umc/js/updater/UpdatesPage.js =================================================================== --- umc/js/updater/UpdatesPage.js (Revision 44882) +++ umc/js/updater/UpdatesPage.js (Arbeitskopie) @@ -46,10 +46,12 @@ ], function(declare, lang, array, all, domClass, topic, sprintf, dialog, tools, store, TitlePane, Page, Form, _) { return declare("umc.modules.updater.UpdatesPage", Page, { + _last_reboot: false, _update_prohibited: false, standby: null, // parents standby method must be passed. weird IE-Bug (#29587) standbyDuring: null, // parents standby method must be passed. weird IE-Bug (#29587) + _update_runnig :false, //will be used to determine if 'check for updates' should be performed depending on if an update process is running or not postMixInProperties: function() { @@ -60,12 +62,23 @@ headerText: _("Available system updates"), helpText: _("Overview of all updates that affect the system as a whole.") }); + + + this.footerButtons = [{ + name: 'showlog', + label: _('Show logfile'), + callback: lang.hitch(this, function() { + this.onClickLog(); + }) + }]; + }, + + buildRendering: function() { this.inherited(arguments); - var widgets = [ // --------------------- Reboot pane ----------------------------- @@ -134,57 +147,77 @@ // FIXME Manual placement: should be done by the layout framework some day. style: 'width:300px;', onValuesLoaded: lang.hitch(this, function(values) { - // TODO check updater/installer/running, don't do anything if something IS running - try - { - this.onQuerySuccess('updater/updates/query'); - var element_releases = this._form.getWidget('releases'); - var to_show = false; - var to_show_msg = true; + + // check if updater is running, don't check for updates if it is + // + // this._update_running will be set to true in case an update is running + // or false if it isn't + // + tools.umcpCommand('updater/installer/running', {}, false).then(lang.hitch(this, function(data) { + this.isRunning = data.result; + if (this.isRunning == "" ) { + // only do this if no update is running + this._update_running=false; + try + { + this.onQuerySuccess('updater/updates/query'); + var element_releases = this._form.getWidget('releases'); + var to_show = false; + var to_show_msg = true; - var element_updatestext = this._form.getWidget('ucs_updates_text'); - element_updatestext.set('content', _("There are no release updates available.")); + var element_updatestext = this._form.getWidget('ucs_updates_text'); + element_updatestext.set('content', _("There are no release updates available.")); - if (values.length) - { - var val = values[values.length-1].id; - to_show = true; - to_show_msg = false; - element_releases.set('value', val); - } + if (values.length) + { + var val = values[values.length-1].id; + to_show = true; + to_show_msg = false; + element_releases.set('value', val); + } - var appliance_mode = (this._form.getWidget('appliance_mode').get('value') === 'true'); - var blocking_component = this._form.getWidget('release_update_blocking_component').get('value'); - if ((blocking_component) && (! appliance_mode)) { - // further updates are available but blocked by specified component which is required for update - element_updatestext.set('content', lang.replace(_("Further release updates are available but cannot be installed because the component '{0}' is not available for newer release versions."), [blocking_component])); - to_show_msg = true; - } + var appliance_mode = (this._form.getWidget('appliance_mode').get('value') === 'true'); + var blocking_component = this._form.getWidget('release_update_blocking_component').get('value'); + if ((blocking_component) && (! appliance_mode)) { + // further updates are available but blocked by specified component which is required for update + element_updatestext.set('content', lang.replace(_("Further release updates are available but cannot be installed because the component '{0}' is not available for newer release versions."), [blocking_component])); + to_show_msg = true; + } + // hide or show combobox, spacers and corresponding button + this._form.showWidget('releases', to_show); + this._form.showWidget('hspacer_180px', to_show); + this._form.showWidget('vspacer_1em', to_show); - // hide or show combobox, spacers and corresponding button - this._form.showWidget('releases', to_show); - this._form.showWidget('hspacer_180px', to_show); - this._form.showWidget('vspacer_1em', to_show); + this._form.showWidget('ucs_updates_text', to_show_msg); - this._form.showWidget('ucs_updates_text', to_show_msg); + var but = this._form._buttons.run_release_update; + but.set('visible', to_show); - var but = this._form._buttons.run_release_update; - but.set('visible', to_show); - - // renew affordance to check for package updates, but only - // if we didn't see availability yet. - if (! this._updates_available) + // renew affordance to check for package updates, but only + // if we didn't see availability yet. + if (! this._updates_available) + { + this._set_updates_button(false, _("Package update status not yet checked")); + this.standbyDuring(all([this._check_dist_upgrade(), this._check_app_updates()])); + } + } + catch(error) { - this._set_updates_button(false, _("Package update status not yet checked")); - } + console.error("onValuesLoaded: " + error.message); + } - this.standbyDuring(all([this._check_dist_upgrade(), this._check_app_updates()])); } - catch(error) - { - console.error("onValuesLoaded: " + error.message); - } - }) + else + { + // notify parent page if update is already running + this.onProgressResume(); + this._update_running=true; + } + })) + }) + + + }, { type: 'HiddenInput', @@ -267,6 +300,11 @@ name: 'app_center_updates_apps', style: 'width:500px;margin-top:.5em;', content: '' + }, + { + type: 'Text', + label: '', + name: 'app_center_updates_link' } ]; @@ -282,9 +320,13 @@ callback: lang.hitch(this, function() { var element = this._form.getWidget('releases'); var release = element.get('value'); - // TODO check updater/installer/running, don't do action if a job is running - this.onRunReleaseUpdate(release); - topic.publish('/umc/actions', this.moduleID, this.moduleFlavor, 'release-update'); + + //check updater/installer/running, don't do action if a job is running + if (! this._update_running){ + + this.onRunReleaseUpdate(release); + topic.publish('/umc/actions', this.moduleID, this.moduleFlavor, 'release-update'); + } }), visible: false }, @@ -292,8 +334,12 @@ name: 'run_packages_update', label: _("Check for package updates"), callback: lang.hitch(this, function() { - this.standbyDuring(this._check_dist_upgrade()); - topic.publish('/umc/actions', this.moduleID, this.moduleFlavor, 'package-update'); + + if (! this._update_running){ + + this.standbyDuring(this._check_dist_upgrade()); + topic.publish('/umc/actions', this.moduleID, this.moduleFlavor, 'package-update'); + } }) }, // If refresh isn't automatic anymore... should we show a "Refresh" button? @@ -316,9 +362,12 @@ name: 'easy_upgrade', label: _("Start Upgrade"), // FIXME Label not correct callback: lang.hitch(this, function() { - // TODO check updater/installer/running, don't do action if a job is running - this.onRunEasyUpgrade(); - topic.publish('/umc/actions', this.moduleID, this.moduleFlavor, 'easy-upgrade'); + + //check updater/installer/running, don't do action if a job is running + if (! this._update_running){ + this.onRunEasyUpgrade(); + topic.publish('/umc/actions', this.moduleID, this.moduleFlavor, 'easy-upgrade'); + } }) } ]; @@ -364,7 +413,7 @@ layout: [ ['app_center_updates_text'], - ['app_center_updates_apps'] + ['app_center_updates_apps', 'app_center_updates_link'] ] } ]; @@ -493,6 +542,7 @@ }, + _update_errata_link: function(version) { var versionWithoutPatchlevel; try { @@ -536,11 +586,12 @@ if (apps.length) { msg = _('There are App Center updates available.'); var appUpdatesInfo = array.map(apps, function(app) { - var link = sprintf('%(name)s', app); - return _('%(name)s: Version %(old)s can be updated to %(new)s', {name: link, old: app.version, 'new': app.candidate_version}); + return _('%(name)s: Version %(old)s can be updated to %(new)s', {name: app.name, old: app.version, 'new': app.candidate_version}); }); var appUpdatesList = '
  • ' + appUpdatesInfo.join('
  • ') + '
'; this._form.getWidget('app_center_updates_apps').set('content', appUpdatesList); + var link = 'href="javascript:void(0)" onclick="require(\'umc/app\').openModule(\'appcenter\')"'; + this._form.getWidget('app_center_updates_link').set('content', _('Please visit the App Center Module to install these updates.', link)); } else { msg = _('There are no App Center updates available.'); } @@ -658,19 +709,23 @@ // First page refresh doesn't work properly when invoked in 'buildRendering()' so // we defer it until the UI is being shown startup: function() { - - this.inherited(arguments); - this._show_reboot_pane(false); - + if (! this._update_running){ + this.inherited(arguments); + this._show_reboot_pane(false); + } }, // ensures refresh whenever we're returning from any action. onShow: function() { - this.inherited(arguments); - // show standby while loading data - this.standby(true); - this.refreshPage(true); + this.inherited(arguments); + // we don't want any 'standby' to interfere with our progress bar if active + if (! this._update_running){ + + this.standby(true); + this.refreshPage(true); + + } }, // should refresh any data contained here. (can be called from outside when needed) @@ -689,6 +744,7 @@ startPolling: function() { // not needed anymore. // this._form.startPolling(); + //this.onProgressResume(); }, // These functions are stubs that the 'updater' Module is listening to, @@ -701,10 +757,15 @@ }, onRunEasyUpgrade: function() { }, + onProgressResume: function() { + }, onStatusLoaded: function(vals) { // event stub + }, + onClickLog: function() { } + }); }); Index: umc/js/updater/_LogViewer.js =================================================================== --- umc/js/updater/_LogViewer.js (Revision 44882) +++ umc/js/updater/_LogViewer.js (Arbeitskopie) @@ -1,291 +0,0 @@ -/* - * Copyright 2011-2013 Univention GmbH - * - * http://www.univention.de/ - * - * All rights reserved. - * - * The source code of this program is made available - * under the terms of the GNU Affero General Public License version 3 - * (GNU AGPL V3) as published by the Free Software Foundation. - * - * Binary versions of this program provided by Univention to you as - * well as other copyrighted, protected or trademarked materials like - * Logos, graphics, fonts, specific documentations and configurations, - * cryptographic keys etc. are subject to a license agreement between - * you and Univention and not subject to the GNU AGPL V3. - * - * In the case you use this program under the terms of the GNU AGPL V3, - * the program is provided 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 with the Debian GNU/Linux or Univention distribution in file - * /usr/share/common-licenses/AGPL-3; if not, see - * . - */ -/*global define window console*/ - -// Class that provides a logfile viewer. Features are: -// -// (1) uses the _PollingMixin to query for the mtime of the named log file -// (2) provides scrolling capability -// (3) can scroll to the bottom of the file if new data has arrived -// (should only work if the current position is at EOF) -// -// the passed query argument must be a backend function that understands -// the 'count' argument specially: -// -// -1 ...... return the file timestamp of the log -// 0 ....... return the whole file contents -// ... return this many last lines (tail -n) - -define([ - "dojo/_base/declare", - "dojo/_base/lang", - "umc/tools", - "umc/widgets/Text", - "umc/widgets/ContainerWidget", - "umc/i18n!umc/modules/updater" -], function(declare, lang, tools, Text, ContainerWidget, _) { - return declare('umc.modules.updater._LogViewer', [ ContainerWidget ], { - - scrollable: true, - _first_call: 3, - _last_stamp: 0, - _check_interval: 0, - _current_job: '', - _log_position: 0, - _max_number_of_lines: 2500, // ~ 200kB if one line ^= 80 chars - _all_lines: [], // hold all past _max_number_of_lines lines - - // FIXME which class should I take here? - style: 'border:1px solid #d0d0d0;background-color:#f8f8f8;padding:.3em;', - - // postMixinProperties: function() { - // - // this.inherited(arguments); - // - // // mix in the polling capability - // lang.mixin(this,umc.modules._updater._PollingMixin({ - // polling: { - // interval: 1000, - // 'function': lang.hitch(this, function() { - // this._fetch_log(); - // }), - // query: this.query - // } - // })); - // }, - - buildRendering: function() { - - this.inherited(arguments); - - this._text = new Text({ - style: 'font-family:monospace;', - content: _("... loading log file ...") - }); - this.addChild(this._text); - }, - - _fetch_log: function() { - - tools.umcpCommand(this.query,{job:this._current_job, count:-1},false).then(lang.hitch(this,function(data) { - - this.onQuerySuccess(this.query + " [count=-1]"); - var stamp = data.result; - if (stamp != this._last_stamp) - { - this._last_stamp = stamp; - tools.umcpCommand(this.query,{job:this._current_job,count:this._log_position},false).then(lang.hitch(this, function(data) { - - var contentLength = parseInt( data.result.length, 10 ); - if( contentLength ) { - this._log_position += contentLength; - } - this.onQuerySuccess(this.query + " [count=0]"); - this.setContentAttr(data.result); - }), - lang.hitch(this, function(data) { - this.onQueryError(this.query + " [count=0]",data); - }) - ); - } - - if (this._check_interval) - { - window.setTimeout(lang.hitch(this,function() { - this._fetch_log(); - }),this._check_interval); - } - - }), - lang.hitch(this,function(data) { - this.onQueryError(this.query + " [count=-1]",data); - // even in case of errors -> reschedule polling! - if (this._check_interval) - { - window.setTimeout(lang.hitch(this,function() { - this._fetch_log(); - }),this._check_interval); - } - }) - ); - - }, - - // set content. Additionally checks if the current scroll position - // (before setting content) is at bottom, and if it is -> set - // bottom position after setting content too. - // Also checks if the log file exceeds a certain limit - setContentAttr: function(lines) { - this._all_lines = this._all_lines.concat(lines); - var printable_lines = this._all_lines; - if (this._lines_exceeded || this._all_lines.length > this._max_number_of_lines) { - var lines_exceeded = this._all_lines.length - this._max_number_of_lines; - this._lines_exceeded += lines_exceeded; - this._all_lines = this._all_lines.slice(lines_exceeded, this._all_lines.length); - var logfile_exceeded = '[...] ' + dojo.replace(_('The log file exceeded {max} lines by {exceeded}. Please see the full logfile.'), - { - max: this._max_number_of_lines, - exceeded: this._lines_exceeded - } - ); - printable_lines = [logfile_exceeded].concat(this._all_lines); - } - var content = printable_lines.join('
\n'); - try - { - var oldpos = this._get_positions(); - - // check if we should scroll to bottom. We avoid that if the current position - // is not at the end, indicating that the user has moved the pane manually. - // - // our height measure doesn't strictly reflect what we need, so we add a little tolerance: - // regard the positon 'at bottom' if its plus/minus 20px around zero - var to_scroll = false; - if ( (this._first_call > 0) || ( /* (oldpos['d_bottom'] > -20) && */ (oldpos.d_bottom < 20))) - { - to_scroll = true; - } - - this._text.set('content', content); - if (to_scroll) - { - this.scrollToBottom(); - if (this._first_call > 0) - { - this._first_call--; - } - } - } - catch(error) - { - console.error("SCROLL ERROR: " + error.message); - } - }, - - // gets the scrolling state of the text widget relative to its container - _get_positions: function() { - - var result = {}; - result.h_text = this._text.contentNode.scrollHeight; // text height - result.h_container = this.domNode.clientHeight; // container widget height - result.d_top = this._text.contentNode.parentNode.scrollTop; // scroll distance from top - result.d_bottom = result.h_text - (result.h_container + result.d_top); // scroll distance from bottom - - return result; - }, - - // scrolls to the bottom of the scroll area. Will be called from different places: - // - // - unconditionally when the ProgressPage is being opened - // - in the 'content' setter if the position is roughly at the bottom - // - scrollToBottom: function() { - - // we ignore any calls to 'scrollToBottom()' if we're not currently - // watching. This makes the pane free movable at the 'return to overview' - // prompt when a job is finished. - if (this._check_interval === 0) - { - return; - } - var todo = true; - var node = this._text.contentNode.parentNode; - var skip = 1024; - while (todo) - { - var oldval = node.scrollTop; - node.scrollTop = oldval+skip; - var newval = node.scrollTop; - - // manually changed? - // or new value not accepted? - if (newval != (oldval+skip)) - { - if (skip > 1) - { - skip = Math.floor(skip / 2); - } - else - { - todo = false; - } - } - } - }, - - // Called from ProgressPage when the log file polling is to be started. - // job key can't be an argument here as we don't know it. - startWatching: function(interval) { - - this._check_interval = interval; - // clean up any stale display and states from last run - this.set('content', _("... loading log file ...")); - this._all_lines = []; - this._lines_exceeded = 0; - - this._first_call = 3; - this._last_stamp = 0; - - this._fetch_log(); // first call, will reschedule itself as long - // as _check_interval is not zero - }, - - // A seperate function that is called by the 'ProgressPage' when the key of the - // current job has become known. - setJobKey: function(job) { - this._current_job = job; - }, - - // effectively stops the polling timer. Can be called from outside (if ProgressPage is being closed) - // or from inside (as 'uninitialize' handler) - // - // Argument 'clean' = TRUE -> also clean up display buffer contents. - onStopWatching: function(clean) { - - this._check_interval = 0; - - if ((typeof(clean) != 'undefined') && (clean)) - { - this.set('content',_("... loading log file ...")); - } - }, - - uninitialize: function() { - - this.inherited(arguments); - this.onStopWatching(); - }, - - // can be listened to from outside - onQueryError: function(subject,data) { - }, - onQuerySuccess: function(subject) { - } - }); -}); Index: umc/js/updater/LogPage.js =================================================================== --- umc/js/updater/LogPage.js (Revision 0) +++ umc/js/updater/LogPage.js (Revision 0) @@ -0,0 +1,150 @@ +/* + * Copyright 2011-2013 Univention GmbH + * + * http://www.univention.de/ + * + * All rights reserved. + * + * The source code of this program is made available + * under the terms of the GNU Affero General Public License version 3 + * (GNU AGPL V3) as published by the Free Software Foundation. + * + * Binary versions of this program provided by Univention to you as + * well as other copyrighted, protected or trademarked materials like + * Logos, graphics, fonts, specific documentations and configurations, + * cryptographic keys etc. are subject to a license agreement between + * you and Univention and not subject to the GNU AGPL V3. + * + * In the case you use this program under the terms of the GNU AGPL V3, + * the program is provided 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 with the Debian GNU/Linux or Univention distribution in file + * /usr/share/common-licenses/AGPL-3; if not, see + * . + */ +/*global define window console*/ + +// Class that provides a scrollable logfile viewer. + +define([ + "dojo/_base/declare", + "dojo/_base/lang", + "umc/tools", + "umc/widgets/Text", + "umc/widgets/ContainerWidget", + "umc/modules/updater/Page", + "umc/widgets/ExpandingTitlePane", + "umc/i18n!umc/modules/updater" +], function(declare, lang, tools, Text, ContainerWidget, Page, ExpandingTitlePane, _) { + return declare('umc.modules.updater.LogPage', Page, { + + _all_lines: [], // hold all past _max_number_of_lines lines + + // FIXME which class should I take here? + style: 'border:1px solid #d0d0d0;background-color:#f8f8f8;padding:.3em;', + + postMixInProperties: function () { + + this.footerButtons = [{ + + name: 'closelog', + align: 'left', + label: _("back"), + callback: lang.hitch(this, function() { + this.onCloseLog(); + }) + }, + { + name: 'jumptoend', + align: 'right', + label: _("jump to end of log"), + callback: lang.hitch(this, function(){ + this.scrollToBottom(); + }) + + }]; + + }, + + + buildRendering: function() { + + this.inherited(arguments); + + this._pane = new ExpandingTitlePane({ + title: _("Log file view") + }); + + this._container = new ContainerWidget ({ + scrollable: true }); + + this.addChild(this._pane); + this._pane.addChild(this._container); + + this._text = new Text({ + style: 'font-family:monospace;', + content: _("... loading log file ...") + }); + this._container.addChild(this._text); + }, + + // read /var/log/univention/updater.log + _fetch_log: function() { + + tools.umcpCommand('updater/installer/logfile', {},false).then(lang.hitch(this, function (data) { + this.onQuerySuccess('updater/installer/logfile'); + this.setContentAttr(data.result); + })); + }, + + + // set content of _text + setContentAttr: function(lines) { + this._all_lines = this._all_lines.concat(lines); + var printable_lines = this._all_lines; + var content = printable_lines.join('
\n'); + this._text.set('content', content); + }, + + + // scrolls to the bottom of the log. + scrollToBottom: function() { + + var todo = true; + var node = this._text.contentNode.parentNode; + var skip = 1024; + while (todo) + { + var oldval = node.scrollTop; + node.scrollTop = oldval+skip; + var newval = node.scrollTop; + + // manually changed? + // or new value not accepted? + if (newval != (oldval+skip)) + { + if (skip > 1) + { + skip = Math.floor(skip / 2); + } + else + { + todo = false; + } + } + } + }, + + // can be listened to from outside + onQueryError: function(subject,data) { + }, + onQuerySuccess: function(subject) { + }, + onCloseLog: function() { + } + }); +}); Eigenschaftsänderungen: umc/js/updater/LogPage.js ___________________________________________________________________ Hinzugefügt: svn:executable + * Index: umc/js/updater/ProgressPage.js =================================================================== --- umc/js/updater/ProgressPage.js (Revision 44882) +++ umc/js/updater/ProgressPage.js (Arbeitskopie) @@ -1,401 +0,0 @@ -/* - * Copyright 2011-2013 Univention GmbH - * - * http://www.univention.de/ - * - * All rights reserved. - * - * The source code of this program is made available - * under the terms of the GNU Affero General Public License version 3 - * (GNU AGPL V3) as published by the Free Software Foundation. - * - * Binary versions of this program provided by Univention to you as - * well as other copyrighted, protected or trademarked materials like - * Logos, graphics, fonts, specific documentations and configurations, - * cryptographic keys etc. are subject to a license agreement between - * you and Univention and not subject to the GNU AGPL V3. - * - * In the case you use this program under the terms of the GNU AGPL V3, - * the program is provided 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 with the Debian GNU/Linux or Univention distribution in file - * /usr/share/common-licenses/AGPL-3; if not, see - * . - */ -/*global define window*/ - -// Some thoughts about the programmatic page structure: -// -// (1) we establish a timer that will check if a job is running. All information -// about the corresponding job come from the Python module, so we will have -// accurate information even if we have closed and reopened the whole module. -// (2) the main purpose of this page is to watch the corresponding log file. This -// is accomplished with a _LogView class that inherits from umc.widgets.Text -// and umc.modules._updater._PollingMixin. -// (3) no matter how the page is closed: the main Module is listening to our -// onStopWatching method to know when our current page can be closed. -// -define([ - "dojo/_base/declare", - "dojo/_base/lang", - "dojo/dom-class", - "umc/dialog", - "umc/tools", - "umc/modules/updater/Page", - "umc/modules/updater/_LogViewer", - "umc/widgets/Button", - "umc/widgets/Text", - "umc/widgets/ExpandingTitlePane", - "umc/modules/lib/server", - "umc/i18n!umc/modules/updater" -], function(declare, lang, domClass, dialog, tools, Page, _LogViewer, Button, Text, ExpandingTitlePane, libServer, _) { - return declare("umc.modules.updater.ProgressPage", Page, { - - // Polling interval for eventually running Updater jobs. If this is - // set to zero it effectively stops the timer. - _interval: 1000, - - _job_key: '', // the key of the currently running job - - _reboot_required: null, - - postMixInProperties: function() { - - this.inherited(arguments); - - // If I don't do that -> the page will switch 'show module help description' off - lang.mixin(this, { - helpText: ' ', - title: _("Update progress") - }); - }, - - buildRendering: function() { - - this.inherited(arguments); - - this._pane = new ExpandingTitlePane({ - title: _("Log file view") - }); - this.addChild(this._pane); - - this._head = new Text({ - region: 'top', - content: _("... please wait ...") - }); - this._pane.addChild(this._head); - - this._log = new _LogViewer({ - region: 'center', - query: 'updater/installer/logfile' - }); - this._pane.addChild(this._log); - - this._log.on('queryerror', lang.hitch(this, 'onQueryError')); - this._log.on('querysuccess', lang.hitch(this, 'onQuerySuccess')); - - // returns to the calling page - this._close = new Button({ - label: _("back"), - region: 'bottom', - onClick: lang.hitch(this, function() { - // local function to close the log view - var _closeLogView = lang.hitch(this, function() { - this.onStopWatching(); - }); - - if (this._reboot_required) { - // show an alert - dialog.alert(_('In order to complete the recently executed action, it is required to reboot the system.')); - _closeLogView(); - } else { - // ask user to restart - libServer.askRestart(_('For the changes to take effect, it is recommended to perform a restart of the UMC server components.')).then( - function() { /* nothing to do */ }, - function() { - // user canceled -> change current view - _closeLogView(); - } - ); - } - - }) - }); - this._pane.addChild(this._close); - this._allow_close(false); - }, - - // starts the polling timer as late as possible. - startup: function() { - - this.inherited(arguments); - this._query_job_status(); - }, - - // callback that processes job status and reschedules itself. - _process_job_status: function(data) { - - if (data !== null) - { - // This is the response that tells us which job is running. As soon as we have this - // key we will ask for the full properties hash until the job is finished. - if (typeof(data.result) == 'string') - { - var txt = data.result; - if (txt !== '') - { - if (this._job_key === '') - { - this._job_key = txt; // from now on, we'll fetch full job details - this._log.setJobKey(txt); // tell the logViewer which job we're referring to. - } - - // if the page is currently in background then we must notify - // our Module that we want to be shown now - this.onJobStarted(); - this._allow_close(false); // close button now invisible. - } - if (data.result !== '') - { - // start the first call for 'update/installer/status' if we got a job name - if ((this._interval) && (! this._timer)) - { - this._timer = window.setTimeout(lang.hitch(this, function() { - this._timer = ''; - this._query_job_status(); - }), this._interval); - } - } - } - else - { - // This knows about all details of the job, and it will know when the job - // is finished. - this._last_job = data.result; // remember for later - - // FIXME Making margins by adding empty lines before and after the text; should - // be done by a style or style class. - var msg = " 
"; - msg = msg + lang.replace(_("The job {label} (started {elapsed} ago) is currently running."), this._last_job); - - if (this._last_job.logfile) - { - msg = msg + ('
' + lang.replace(_("You're currently watching its log file {logfile}"), this._last_job)); - } - msg = msg + "
 
"; - - - this._head.set('content', msg); - - // if (! data.result['running']) - // { - // } - - if (data.result.running) - { - // reschedule this as long as the job runs. - if ((this._interval) && (! this._timer)) - { - this._timer = window.setTimeout(lang.hitch(this, function() { - this._timer = ''; - this._query_job_status(); - }), this._interval); - } - } - else - { - this._allow_close(true); // does the rest. - } - - this._pane.layout(); - - } - } - else { - // error case, request could not been sent... try again - if ((this._interval) && (! this._timer)) - { - this._timer = window.setTimeout(lang.hitch(this, function() { - this._timer = ''; - this._query_job_status(); - }), this._interval); - } - } - - }, - - // queries job status. As long as we know a job key -> ask for full - // details. The handler _process_job_status() handles this gracefully. - _query_job_status: function() { - - if (this._job_key === '') - { - tools.umcpCommand( - 'updater/installer/running', {}, false).then( - lang.hitch(this, function(data) { - this.onQuerySuccess('updater/installer/running'); - this._process_job_status(data); - }), - lang.hitch(this, function(data) { - this.onQueryError('updater/installer/running', data); // handles error - this._process_job_status(null); // only for rescheduling - }) - ); - } - else - { - tools.umcpCommand('updater/installer/status', {job:this._job_key}, false).then( - lang.hitch(this, function(data) { - this.onQuerySuccess("updater/installer/status(" + this._job_key + ")"); - this._process_job_status(data); - }), - lang.hitch(this, function(data) { - this.onQueryError('updater/installer/status', data); // handles error - this._process_job_status(null); // only for rescheduling - }) - ); - } - }, - - // switches visibility of our 'close' button on or off. - // Additionally, changes some labels to reflect the current situation. - _allow_close: function(yes) { - domClass.toggle(this._close.domNode, 'dijitHidden', ! yes); - // While the button is hidden, the polling callback maintains the content - // of this._head. Only if Close is enabled -> set to a different text. - if (yes) - { - if ((this._job_key !== '') && (this._last_job)) - { - // First thing to do: notify the Module that the job is finished. So it can already - // refresh the 'Updates' and 'Components' pages before the user gets back there. - this.onJobFinished(); - - // FIXME Manually making empty lines before and after this text; should better be done - // by a style or a style class. - var msg = " 
"; - msg = msg + lang.replace(_("The current job ({label}) is now finished.
"), this._last_job); - if (this._last_job.elapsed !== undefined) - { - msg = msg + lang.replace(_("It took {elapsed} to complete.
"), this._last_job); - } - msg = msg + _("You may return to the overview by clicking the 'back' button now."); - msg = msg + "
 
"; - - this._head.set('content', msg); - - // set headers according to the outcome - var status = 'success'; - var lstat = this._last_job._status_; - if ((lstat === undefined) || (lstat != 'DONE')) - { - status = 'failed'; - } - this._switch_headings(status); - this._log.scrollToBottom(); // jump to bottom a very last time - this._log.onStopWatching(); // now log is freely scrollable manually - - this._last_job = null; // can be deleted, but this._job_key should be retained! - } - } - }, - - // gives a means to restart polling after reauthentication - startPolling: function() { - this._process_job_status(null); - }, - - // This function will be called when the (background) ProgressPage encounters - // that a job has been started. The updater Module listens here and will then - // call startWatching. - onJobStarted: function() { - }, - - // This function will be called when the already opened ProgressPage encounters - // the end of the current job. The updater Module listens here and will refresh - // the 'Updates' and 'Components' pages. - onJobFinished: function() { - }, - - // updater Module calls this when the ProgressPage is to be opened. - startWatching: function() { - - // ensure a clean look (and not some stale text from last job) - this._head.set('content', _("... loading job data ...")); - - this._allow_close(false); // forbid closing this tab. - this._log.startWatching(this._interval); // start logfile tail - }, - - // updater Module listens to this event to close the page - // - // This is a good place to reset the log viewer contents too. - onStopWatching: function() { - this._job_key = ''; - this._last_job = null; - this._log.onStopWatching(true); - }, - - // lets the timer loop stop when the module is closed. - uninitialize: function() { - - this.inherited(arguments); - this._interval = 0; - }, - - // on switch to this page: set initial headings, and fetch - // the 'job running' status at least once. - onShow: function() { - this._switch_headings('running'); - this._query_job_status(); - }, - - // internal function that switches any heading variables of - // our current page, according to the retrieved job status - _switch_headings: function(status) { - - // avoid doing that repeatedly - if (status == this._last_heading_status) - { - return; - } - - this._last_heading_status = status; - - var headings = { - 'running': { - // title: _("Update in progress"), - headerText: _("Univention Updater is working"), - helpText: _("As long as the Univention Updater is updating your system, you're not allowed to manage settings. You may watch the progress, or close the module.") - }, - 'success': { - // title: _("Update finished"), - headerText: _("Univention Updater job completed"), - helpText: _("Univention Updater has successfully finished the current job. You may read through the log file. If you're finished you may press the 'back' button to close this view.") - }, - 'failed': { - // title: _("Update failed"), - headerText: _("Univention Updater job failed"), - helpText: _("Univention Updater could not successfully complete the current job. The log file should show the cause of the failure. If you're finished examining the log file you may press the 'back' button to close this view.") - } - }; - - var info = headings[status]; - for (var v in info) - { - this.set(v, info[v]); - } - // this.layout(); - - }, - - updateStatus: function(values) { - // receive new status values from update page - this._reboot_required = tools.isTrue(values.reboot_required); - } - }); -}); Index: umc/js/de.po =================================================================== --- umc/js/de.po (Revision 44882) +++ umc/js/de.po (Arbeitskopie) @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: univention-management-console-module-updater\n" "Report-Msgid-Bugs-To: packages@univention.de\n" -"POT-Creation-Date: 2013-08-26 10:40+0200\n" +"POT-Creation-Date: 2013-10-01 06:51+0200\n" "PO-Revision-Date: 2012-02-27 16:03+0100\n" "Last-Translator: Frank Greif \n" "Language-Team: LANGUAGE \n" @@ -12,46 +12,37 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: umc/js/updater/UpdatesPage.js:543 +#: umc/js/updater/UpdatesPage.js:589 #, python-format msgid "%(name)s: Version %(old)s can be updated to %(new)s" msgstr "%(name)s: Version %(old)s kann auf %(new)s aktualisiert werden" -#: umc/js/updater/UpdatesPage.js:229 umc/js/updater/UpdatesPage.js:261 +#: umc/js/updater/UpdatesPage.js:263 umc/js/updater/UpdatesPage.js:295 msgid "... loading data ..." msgstr "... Daten werden geladen ..." -#: umc/js/updater/ProgressPage.js:328 -msgid "... loading job data ..." -msgstr "... Daten werden geladen ..." - -#: umc/js/updater/_LogViewer.js:89 umc/js/updater/_LogViewer.js:248 -#: umc/js/updater/_LogViewer.js:275 +#: umc/js/updater/LogPage.js:90 msgid "... loading log file ..." msgstr "... Protokolldatei wird geladen ..." -#: umc/js/updater/ProgressPage.js:88 -msgid "... please wait ..." -msgstr "... bitte warten ..." - -#: umc/js/updater.js:181 +#: umc/js/updater.js:212 msgid "1 package to be REMOVED" msgstr "1 Paket wird ENTFERNT" -#: umc/js/updater.js:219 +#: umc/js/updater.js:250 msgid "1 package to be installed" msgstr "1 Paket wird NEU installiert" -#: umc/js/updater.js:200 +#: umc/js/updater.js:231 msgid "1 package to be updated" msgstr "1 Paket wird aktualisiert" -#: umc/js/updater.js:310 +#: umc/js/updater.js:341 msgid "Again, DO NOT power off the system even in these cases!" msgstr "" "Noch einmal: Schalten Sie das System auch unter diesen Umständen NICHT aus." -#: umc/js/updater.js:483 +#: umc/js/updater.js:520 msgid "" "Alternatively, you may close the current Management Console window, wait " "some time, and try to open it again." @@ -59,57 +50,52 @@ "Sie können die Management Console jetzt auch schließen, und später wieder " "öffnen." -#: umc/js/updater/UpdatesPage.js:367 +#: umc/js/updater.js:421 +msgid "An error has occurred :" +msgstr "Ein Fehler ist aufgetreten :" + +#: umc/js/updater/UpdatesPage.js:412 msgid "App Center updates" msgstr "App Center-Aktualisierungen" -#: umc/js/updater/ProgressPage.js:373 -msgid "" -"As long as the Univention Updater is updating your system, you're not " -"allowed to manage settings. You may watch the progress, or close the module." -msgstr "" -"Solange Univention Updater Ihr System aktualisiert, können Sie keine " -"Einstellungen verändern. Sie können die Aktualisierung hier verfolgen oder " -"das Modul schließen." - -#: umc/js/updater.js:290 +#: umc/js/updater.js:321 msgid "Attention!" msgstr "Achtung!" -#: umc/js/updater/UpdatesPage.js:59 +#: umc/js/updater/UpdatesPage.js:62 msgid "Available system updates" msgstr "Verfügbare System-Updates" -#: umc/js/updater.js:242 umc/js/updater.js:326 -#: umc/js/updater/UpdatesPage.js:647 +#: umc/js/updater.js:273 umc/js/updater.js:357 +#: umc/js/updater/UpdatesPage.js:693 msgid "Cancel" msgstr "Abbrechen" -#: umc/js/updater/UpdatesPage.js:297 umc/js/updater/UpdatesPage.js:526 +#: umc/js/updater/UpdatesPage.js:335 umc/js/updater/UpdatesPage.js:572 msgid "Check for package updates" msgstr "Paket-Aktualisierungen prüfen" -#: umc/js/updater.js:476 +#: umc/js/updater.js:513 msgid "Connection lost!" msgstr "Verbindung zum Server unterbrochen!" -#: umc/js/updater.js:469 +#: umc/js/updater.js:506 msgid "Connection to server lost. Trying to reconnect." msgstr "" "Die Verbindung zum Server wurde unterbrochen. Ein erneuter Verbindungsaufbau " "wird gestartet." -#: umc/js/updater.js:306 +#: umc/js/updater.js:337 msgid "DO NOT power off the system during the update." msgstr "Schalten Sie das System während des Updates NICHT aus." -#: umc/js/updater.js:124 +#: umc/js/updater.js:118 msgid "Do you really want to install release updates up to version {release}?" msgstr "" "Möchten Sie wirklich alle Release-Aktualisierungen bis zur Version " "'{release}' installieren?" -#: umc/js/updater.js:234 +#: umc/js/updater.js:265 msgid "" "Do you really want to perform the update/install/remove of the above " "packages?" @@ -117,23 +103,23 @@ "Möchten Sie wirklich die genannten Pakete aktualisieren, installieren bzw. " "entfernen?" -#: umc/js/updater/UpdatesPage.js:644 +#: umc/js/updater/UpdatesPage.js:690 msgid "Do you really want to reboot the machine?" msgstr "Möchten Sie die Maschine jetzt neu starten?" -#: umc/js/updater.js:137 +#: umc/js/updater.js:131 msgid "Do you really want to upgrade your system?" msgstr "Möchten Sie Ihr System jetzt aktualisieren?" -#: umc/js/updater.js:319 +#: umc/js/updater.js:350 msgid "Do you really wish to proceed?" msgstr "Möchten Sie wirklich fortfahren?" -#: umc/js/updater/UpdatesPage.js:81 +#: umc/js/updater/UpdatesPage.js:95 msgid "During reboot, the connection to the system will be lost. " msgstr "Während des Neustarts wird die Verbindung zum System unterbrochen. " -#: umc/js/updater.js:298 +#: umc/js/updater.js:329 msgid "" "During setup, the web server may be stopped, leading to a termination of the " "HTTP connection. " @@ -141,7 +127,7 @@ "Während des Updates ist es möglich, dass die Verbindung zum Webserver " "unterbrochen wird. " -#: umc/js/updater/ProgressPage.js:117 +#: umc/js/updater.js:178 msgid "" "For the changes to take effect, it is recommended to perform a restart of " "the UMC server components." @@ -149,7 +135,7 @@ "Damit die Änderungen wirksam werden, ist es empfohlen einen Neustart der UMC-" "Server-Komponenten durchzuführen." -#: umc/js/updater/UpdatesPage.js:159 umc/js/updater/UpdatesPage.js:446 +#: umc/js/updater/UpdatesPage.js:183 umc/js/updater/UpdatesPage.js:491 msgid "" "Further release updates are available but cannot be installed because the " "component '{0}' is not available for newer release versions." @@ -158,7 +144,7 @@ "werden, da die Komponente '{0}' noch nicht für neuere Releaseversionen " "bereitgestellt wurde." -#: umc/js/updater.js:293 +#: umc/js/updater.js:324 msgid "" "In normal case, trouble-free use by users is not possible during the update, " "since system services may need to be restarted. " @@ -166,7 +152,7 @@ "Im Normalfall ist während des Updates kein störungsfreies Arbeiten von " "Anwendern möglich, da beispielsweise Dienste neu gestartet werden. " -#: umc/js/updater/ProgressPage.js:113 umc/js/updater/UpdatesPage.js:88 +#: umc/js/updater.js:175 umc/js/updater/UpdatesPage.js:102 msgid "" "In order to complete the recently executed action, it is required to reboot " "the system." @@ -174,23 +160,23 @@ "Um die kürzlich ausgeführte Aktion abzuschließen, ist es erforderlich, das " "System neu zu starten." -#: umc/js/updater/UpdatesPage.js:511 +#: umc/js/updater/UpdatesPage.js:557 msgid "Information about the updates" msgstr "Informationen zu den Aktualisierungen" -#: umc/js/updater.js:246 umc/js/updater.js:329 +#: umc/js/updater.js:277 umc/js/updater.js:360 msgid "Install" msgstr "Installieren" -#: umc/js/updater/UpdatesPage.js:525 +#: umc/js/updater/UpdatesPage.js:571 msgid "Install package updates" msgstr "Paket-Aktualisierungen installieren" -#: umc/js/updater/UpdatesPage.js:285 +#: umc/js/updater/UpdatesPage.js:319 msgid "Install release update" msgstr "Release-Aktualisierungen installieren" -#: umc/js/updater.js:292 +#: umc/js/updater.js:323 msgid "" "Installing a system update is a significant change to this system and could " "have impact to other systems. " @@ -198,7 +184,7 @@ "Das Einspielen eines Updates ist eine signifikante Veränderung des " "betreffenden Systems, die auch Auswirkungen auf andere Systeme haben kann. " -#: umc/js/updater.js:295 +#: umc/js/updater.js:326 msgid "" "It is also recommended to evaluate the update in a test environment and to " "create a backup of the system." @@ -206,19 +192,15 @@ "Tests in einer Testumgebung und die Erstellung einer Sicherung des Systems " "werden ebenfalls empfohlen." -#: umc/js/updater/ProgressPage.js:284 -msgid "It took {elapsed} to complete.
" -msgstr "Er hat {elapsed} benötigt.
" - -#: umc/js/updater/ProgressPage.js:82 +#: umc/js/updater/LogPage.js:79 msgid "Log file view" msgstr "Protokoll" -#: umc/js/updater.js:300 +#: umc/js/updater.js:331 msgid "Logfiles can be found in the directory /var/log/univention/." msgstr "Logdateien können im Verzeichnis /var/log/univention/ gefunden werden." -#: umc/js/updater.js:299 +#: umc/js/updater.js:330 msgid "" "Nonetheless, the update proceeds and the update can be monitored from a new " "UMC session. " @@ -226,24 +208,24 @@ "Das Update wird trotzdem weiter durchgeführt, der Vorgang kann in einer " "neuen UMC-Sitzung weiter beobachtet werden. " -#: umc/js/updater/UpdatesPage.js:60 +#: umc/js/updater/UpdatesPage.js:63 msgid "Overview of all updates that affect the system as a whole." msgstr "" "Überblick über Software-Aktualisierungen, die das Gesamtsystem betreffen" -#: umc/js/updater/UpdatesPage.js:177 umc/js/updater/UpdatesPage.js:248 +#: umc/js/updater/UpdatesPage.js:200 umc/js/updater/UpdatesPage.js:282 msgid "Package update status not yet checked" msgstr "Der Paket-Aktualisierungsstatus wurde noch nicht geprüft." -#: umc/js/updater/UpdatesPage.js:359 +#: umc/js/updater/UpdatesPage.js:404 msgid "Package updates" msgstr "Paket-Aktualisierungen" -#: umc/js/updater/UpdatesPage.js:574 +#: umc/js/updater/UpdatesPage.js:620 msgid "Package updates are available." msgstr "Es sind Paket-Aktualisierungen verfügbar." -#: umc/js/updater.js:303 +#: umc/js/updater.js:334 msgid "" "Please also consider the release notes, changelogs and references posted in " "the Univention Forum." @@ -252,46 +234,58 @@ "jeweiligen Update in dem Univention " "Forum." -#: umc/js/updater/UpdatesPage.js:548 +#: umc/js/updater/UpdatesPage.js:594 #, python-format msgid "Please visit the App Center Module to install these updates." msgstr "" "Bitte öffnen Sie das App Center Modul, um diese Aktualisierungen " "zu installieren." -#: umc/js/updater/UpdatesPage.js:313 umc/js/updater/UpdatesPage.js:651 +#: umc/js/updater/UpdatesPage.js:355 umc/js/updater/UpdatesPage.js:697 msgid "Reboot" msgstr "Neu starten" -#: umc/js/updater/UpdatesPage.js:333 +#: umc/js/updater/UpdatesPage.js:378 msgid "Reboot required" msgstr "Neustart erforderlich" -#: umc/js/updater/UpdatesPage.js:306 +#: umc/js/updater/UpdatesPage.js:348 msgid "Refresh" msgstr "Aktualisieren" -#: umc/js/updater/UpdatesPage.js:341 +#: umc/js/updater/UpdatesPage.js:386 msgid "Release information" msgstr "Aktueller Status" -#: umc/js/updater/UpdatesPage.js:349 +#: umc/js/updater/UpdatesPage.js:394 msgid "Release updates" msgstr "Release-Aktualisierungen" -#: umc/js/updater/UpdatesPage.js:321 +#: umc/js/updater.js:421 +msgid "See the log for further info !" +msgstr "Weitere Infos entnehmen Sie bitte dem Protokoll !" + +#: umc/js/updater/UpdatesPage.js:69 +msgid "Show logfile" +msgstr "Protokoll anzeigen" + +#: umc/js/updater/UpdatesPage.js:363 msgid "Start Upgrade" msgstr "Aktualisierung starten" -#: umc/js/updater.js:236 +#: umc/js/updater.js:267 msgid "Start Upgrade?" msgstr "Aktualisierung starten?" -#: umc/js/updater/UpdatesPage.js:555 +#: umc/js/updater.js:412 +msgid "Starting the update process..." +msgstr "Starte der Aktualisierung..." + +#: umc/js/updater/UpdatesPage.js:601 msgid "The App Center is not available or currently unreachable" msgstr "Das App Center ist nicht verfügbar oder momentan nicht erreichbar" -#: umc/js/updater.js:354 +#: umc/js/updater.js:385 msgid "" "The Univention Updater action could not be started [Error {status}]: " "{message}" @@ -299,11 +293,11 @@ "Der Univention Updater konnte nicht gestartet werden [Fehler {status}]: " "{message}" -#: umc/js/updater/UpdatesPage.js:79 +#: umc/js/updater/UpdatesPage.js:93 msgid "The computer is now rebooting. " msgstr "Der Computer wird jetzt neu gestartet. " -#: umc/js/updater.js:482 +#: umc/js/updater.js:519 msgid "" "The connection to the server was lost, trying to reconnect. You may need to " "re-authenticate when the connection is restored." @@ -312,134 +306,77 @@ "wieder aufzunehmen. Wahrscheinlich müssen Sie sich neu anmelden, wenn die " "Verbindung wieder hergestellt ist." -#: umc/js/updater/ProgressPage.js:281 -msgid "The current job ({label}) is now finished.
" -msgstr "Der aktuelle Vorgang ({label}) ist jetzt beendet.
" - -#: umc/js/updater/UpdatesPage.js:431 +#: umc/js/updater/UpdatesPage.js:476 msgid "The currently installed release version is {ucs_version}" msgstr "Die momentan installierte Version ist {ucs_version}" -#: umc/js/updater/UpdatesPage.js:429 +#: umc/js/updater/UpdatesPage.js:474 msgid "" "The currently installed release version is {ucs_version} errata{erratalevel}" msgstr "" "Die momentan installierte Version ist {ucs_version} errata{erratalevel}" -#: umc/js/updater/ProgressPage.js:183 -msgid "The job {label} (started {elapsed} ago) is currently running." -msgstr "" -"Momentan läuft der Aktualisierungsauftrag {label} (gestartet vor " -"{elapsed})" - -#: umc/js/updater/_LogViewer.js:151 +#: umc/js/updater.js:339 msgid "" -"The log file exceeded {max} lines by {exceeded}. Please see the full logfile." -msgstr "" -"Das Protokoll hat {max} Zeilen um {exceeded} überschritten. Bitte überprüfen " -"Sie das gesamte Protokoll." - -#: umc/js/updater.js:308 -msgid "" "The update can take a long time and the system may respond slowly. You may " "be temporarily unable to log in." msgstr "" "Das Update kann eine lange Zeit in Anspruch nehmen und Ihr System träge " "reagieren. Es ist möglich, dass Sie sich zeitweise nicht neu anmelden können." -#: umc/js/updater/UpdatesPage.js:541 +#: umc/js/updater.js:423 +msgid "The update process was successful." +msgstr "Der Updatevorgang war erfolgreich." + +#: umc/js/updater/UpdatesPage.js:587 msgid "There are App Center updates available." msgstr "Es sind App Center-Aktualisierungen verfügbar." -#: umc/js/updater/UpdatesPage.js:550 +#: umc/js/updater/UpdatesPage.js:596 msgid "There are no App Center updates available." msgstr "Es sind keine App Center-Aktualisierungen verfügbar." -#: umc/js/updater/UpdatesPage.js:575 +#: umc/js/updater/UpdatesPage.js:621 msgid "There are no package updates available." msgstr "Es sind keine Paket-Aktualisierungen verfügbar." -#: umc/js/updater/UpdatesPage.js:145 umc/js/updater/UpdatesPage.js:235 +#: umc/js/updater/UpdatesPage.js:169 umc/js/updater/UpdatesPage.js:269 msgid "There are no release updates available." msgstr "Es sind keine Release-Aktualisierungen verfügbar." -#: umc/js/updater/UpdatesPage.js:448 +#: umc/js/updater/UpdatesPage.js:493 msgid "There are no updates available." msgstr "Es sind keine Aktualisierungen verfügbar." -#: umc/js/updater/UpdatesPage.js:444 +#: umc/js/updater/UpdatesPage.js:489 msgid "There are updates available." msgstr "Es sind Aktualisierungen verfügbar." -#: umc/js/updater/UpdatesPage.js:80 +#: umc/js/updater/UpdatesPage.js:94 msgid "This may take some time. Please be patient. " msgstr "Das kann einige Zeit dauern. Bitte haben Sie etwas Geduld. " -#: umc/js/updater.js:294 +#: umc/js/updater.js:325 msgid "Thus, updates shouldn't be installed on a live system. " msgstr "Deshalb sollten Sie das Update nicht im laufenden Betrieb einspielen. " -#: umc/js/updater/ProgressPage.js:383 -msgid "" -"Univention Updater could not successfully complete the current job. The log " -"file should show the cause of the failure. If you're finished examining the " -"log file you may press the 'back' button to close this view." -msgstr "" -"Univention Updater konnte den aktuellen Auftrag nicht erfolgreich " -"abschließen. Im Protokoll sollten Sie die Ursache des Fehlschlages sehen " -"können. Der Knopf 'Zurück' schließt die aktuelle Ansicht." - -#: umc/js/updater/ProgressPage.js:378 -msgid "" -"Univention Updater has successfully finished the current job. You may read " -"through the log file. If you're finished you may press the 'back' button to " -"close this view." -msgstr "" -"Univention Updater hat den aktuellen Auftrag erfolgreich abgeschlossen. Sie " -"können sich das Protokoll noch anschauen. Drücken Sie dann den 'Zurück' " -"Knopf, um die Ansicht zu schließen und zur Übersicht zurückzukehren." - -#: umc/js/updater/ProgressPage.js:372 -msgid "Univention Updater is working" -msgstr "Univention Updater ist gerade aktiv" - -#: umc/js/updater/ProgressPage.js:377 -msgid "Univention Updater job completed" -msgstr "Univention Updater Auftrag abgeschlossen" - -#: umc/js/updater/ProgressPage.js:382 -msgid "Univention Updater job failed" -msgstr "Univention Updater Auftrag ist fehlgeschlagen" - -#: umc/js/updater/UpdatesPage.js:578 +#: umc/js/updater/UpdatesPage.js:624 msgid "Update availability could not be checked." msgstr "Verfügbarkeit von Aktualisierungen konnte nicht geprüft werden." -#: umc/js/updater/ProgressPage.js:381 -msgid "Update failed" -msgstr "Aktualisierung fehlgeschlagen" +#: umc/js/updater.js:421 +msgid "Update error" +msgstr "Aktualisierungsfehler" -#: umc/js/updater/ProgressPage.js:376 -msgid "Update finished" -msgstr "Aktualisierung abgeschlossen" - -#: umc/js/updater/ProgressPage.js:371 -msgid "Update in progress" -msgstr "Aktualisierung läuft" - -#: umc/js/updater/ProgressPage.js:73 -msgid "Update progress" -msgstr "Updatevorgang" - -#: umc/js/updater/UpdatesPage.js:127 +#: umc/js/updater/UpdatesPage.js:141 msgid "Update system up to release" msgstr "System bis zu dieser Version aktualisieren" -#: umc/js/updater/UpdatesPage.js:58 +#: umc/js/updater/UpdatesPage.js:61 msgid "Updates" msgstr "Aktualisierungen" -#: umc/js/updater/UpdatesPage.js:82 +#: umc/js/updater/UpdatesPage.js:96 msgid "" "When the connection is back you will be prompted to authenticate yourself " "again." @@ -447,17 +384,7 @@ "Wenn die Verbindung wieder hergestellt ist, werden Sie aufgefordert, sich " "noch einmal neu anzumelden." -#: umc/js/updater/ProgressPage.js:286 -msgid "You may return to the overview by clicking the 'back' button now." -msgstr "" -"Sie können jetzt zur Übersicht zurückkehren, indem Sie den 'Zurück'-Knopf " -"drücken." - -#: umc/js/updater/ProgressPage.js:187 -msgid "You're currently watching its log file {logfile}" -msgstr "Sie sehen die Protokolldatei {logfile}" - -#: umc/js/updater.js:454 +#: umc/js/updater.js:491 msgid "" "Your current session has expired, or the connection to the server was lost. " "You must authenticate yourself again." @@ -465,24 +392,112 @@ "Ihre aktuelle Sitzung ist abgelaufen, oder die Verbindung zum Server war " "verlorengegangen. Sie müssen sich noch einmal neu anmelden." -#: umc/js/updater/ProgressPage.js:103 +#: umc/js/updater/LogPage.js:56 msgid "back" msgstr "Zurück" -#: umc/js/updater.js:185 +#: umc/js/updater/LogPage.js:64 +msgid "jump to end of log" +msgstr "Zum Ende des Protokolls springen" + +#: umc/js/updater.js:216 msgid "{count} packages to be REMOVED" msgstr "{count} Pakete werden ENTFERNT" -#: umc/js/updater.js:223 +#: umc/js/updater.js:254 msgid "{count} packages to be installed" msgstr "{count} Pakete werden NEU installiert" -#: umc/js/updater.js:204 +#: umc/js/updater.js:235 msgid "{count} packages to be updated" msgstr "{count} Pakete werden aktualisiert" +#~ msgid "... loading job data ..." +#~ msgstr "... Daten werden geladen ..." + +#~ msgid "... please wait ..." +#~ msgstr "... bitte warten ..." + #~ msgid "Application updates available" #~ msgstr "Aktualisierungen für Applikationen verfügbar" +#~ msgid "" +#~ "As long as the Univention Updater is updating your system, you're not " +#~ "allowed to manage settings. You may watch the progress, or close the " +#~ "module." +#~ msgstr "" +#~ "Solange Univention Updater Ihr System aktualisiert, können Sie keine " +#~ "Einstellungen verändern. Sie können die Aktualisierung hier verfolgen " +#~ "oder das Modul schließen." + +#~ msgid "It took {elapsed} to complete.
" +#~ msgstr "Er hat {elapsed} benötigt.
" + #~ msgid "No application updates available" #~ msgstr "Keine Aktualisierungen für Applikationen verfügbar" + +#~ msgid "The current job ({label}) is now finished.
" +#~ msgstr "Der aktuelle Vorgang ({label}) ist jetzt beendet.
" + +#~ msgid "The job {label} (started {elapsed} ago) is currently running." +#~ msgstr "" +#~ "Momentan läuft der Aktualisierungsauftrag {label} (gestartet vor " +#~ "{elapsed})" + +#~ msgid "" +#~ "The log file exceeded {max} lines by {exceeded}. Please see the full " +#~ "logfile." +#~ msgstr "" +#~ "Das Protokoll hat {max} Zeilen um {exceeded} überschritten. Bitte " +#~ "überprüfen Sie das gesamte Protokoll." + +#~ msgid "This may take some time. Please be patient." +#~ msgstr "Das kann einige Zeit dauern. Bitte haben Sie etwas Geduld. " + +#~ msgid "" +#~ "Univention Updater could not successfully complete the current job. The " +#~ "log file should show the cause of the failure. If you're finished " +#~ "examining the log file you may press the 'back' button to close this view." +#~ msgstr "" +#~ "Univention Updater konnte den aktuellen Auftrag nicht erfolgreich " +#~ "abschließen. Im Protokoll sollten Sie die Ursache des Fehlschlages sehen " +#~ "können. Der Knopf 'Zurück' schließt die aktuelle Ansicht." + +#~ msgid "" +#~ "Univention Updater has successfully finished the current job. You may " +#~ "read through the log file. If you're finished you may press the 'back' " +#~ "button to close this view." +#~ msgstr "" +#~ "Univention Updater hat den aktuellen Auftrag erfolgreich abgeschlossen. " +#~ "Sie können sich das Protokoll noch anschauen. Drücken Sie dann den " +#~ "'Zurück' Knopf, um die Ansicht zu schließen und zur Übersicht " +#~ "zurückzukehren." + +#~ msgid "Univention Updater is working" +#~ msgstr "Univention Updater ist gerade aktiv" + +#~ msgid "Univention Updater job completed" +#~ msgstr "Univention Updater Auftrag abgeschlossen" + +#~ msgid "Univention Updater job failed" +#~ msgstr "Univention Updater Auftrag ist fehlgeschlagen" + +#~ msgid "Update failed" +#~ msgstr "Aktualisierung fehlgeschlagen" + +#~ msgid "Update finished" +#~ msgstr "Aktualisierung abgeschlossen" + +#~ msgid "Update in progress" +#~ msgstr "Aktualisierung läuft" + +#~ msgid "Updating system..." +#~ msgstr "Aktualisiere System" + +#~ msgid "You may return to the overview by clicking the 'back' button now." +#~ msgstr "" +#~ "Sie können jetzt zur Übersicht zurückkehren, indem Sie den 'Zurück'-Knopf " +#~ "drücken." + +#~ msgid "You're currently watching its log file {logfile}" +#~ msgstr "Sie sehen die Protokolldatei {logfile}"