Created
October 28, 2011 18:17
-
-
Save sjl/1322959 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/README.markdown b/README.markdown | |
index d34e76b..42029fb 100644 | |
--- a/README.markdown | |
+++ b/README.markdown | |
@@ -72,3 +72,12 @@ standard Django one, you just have to run (while the virtualenv is activated): | |
pip install werkzeug | |
And then use `./dev-runserver.sh plus` to run it. | |
+ | |
+### bpython shell | |
+ | |
+If you want to use the awesome bpython shell instead of the normal one you just | |
+need to run (while the virtualenv is activated): | |
+ | |
+ pip install bpython | |
+ | |
+Now when you run `pm shell` it will use bpython automatically. | |
diff --git a/apps/videos/models.py b/apps/videos/models.py | |
index 7baf7ad..3807dd6 100644 | |
--- a/apps/videos/models.py | |
+++ b/apps/videos/models.py | |
@@ -670,7 +670,7 @@ class SubtitleLanguage(models.Model): | |
else: | |
return self.is_complete | |
- def get_widget_url(self): | |
+ def get_widget_url(self, mode=None): | |
# duplicates unisubs.widget.SubtitleDialogOpener.prototype.openDialogOrRedirect_ | |
video = self.video | |
video_url = video.get_video_url() | |
@@ -680,7 +680,8 @@ class SubtitleLanguage(models.Model): | |
"effectiveVideoURL": video_url, | |
"languageCode": self.language, | |
"subLanguagePK": self.pk, | |
- "originalLanguageCode": video.language } | |
+ "originalLanguageCode": video.language, | |
+ "mode": mode, } | |
if self.is_dependent(): | |
config['baseLanguagePK'] = self.standard_language and self.standard_language.pk | |
return reverse('onsite_widget')+'?config='+urlquote_plus(json.dumps(config)) | |
diff --git a/apps/widget/views.py b/apps/widget/views.py | |
index 589bd30..c772991 100644 | |
--- a/apps/widget/views.py | |
+++ b/apps/widget/views.py | |
@@ -23,11 +23,12 @@ from django.template.defaultfilters import urlize, linebreaks, force_escape | |
from django.shortcuts import render_to_response, redirect | |
from django.utils.http import cookie_date | |
from django.contrib.sites.models import Site | |
+from django.core.urlresolvers import reverse | |
from django.template import RequestContext | |
from videos import models | |
from widget.srt_subs import captions_and_translations_to_srt, captions_to_srt, SSASubtitles | |
import simplejson as json | |
-from simplejson.decoder import JSONDecodeError, JSONDecodeError | |
+from simplejson.decoder import JSONDecodeError | |
from django.conf import settings | |
from django.views.decorators.csrf import csrf_exempt | |
import widget | |
@@ -105,12 +106,19 @@ def onsite_widget(request): | |
if not 'effectiveVideoURL' in config: | |
config['effectiveVideoURL'] = video.get_video_url() | |
- team_videos = list(video.teamvideo_set.all()[:1]) | |
+ team_videos = list(video.teamvideo_set.all().select_related('team')[:1]) | |
if team_videos: | |
+ team = team_videos[0].team | |
+ | |
config['guidelines'] = dict( | |
[(s.key_name.split('_', 1)[-1], | |
linebreaks(urlize(force_escape(s.data)))) | |
- for s in team_videos[0].team.settings.guidelines()]) | |
+ for s in team.settings.guidelines() | |
+ if s.data.strip()]) | |
+ | |
+ # TODO: Go to the tasks panel once the history stuff is implemented | |
+ config['team_url'] = reverse('teams:settings', | |
+ kwargs={'slug': team.slug}) | |
else: | |
config['guidelines'] = {} | |
@@ -138,7 +146,7 @@ def onsite_widget_resume(request): | |
if not video_id: | |
raise Http404 | |
- video = get_object_or_404(models.Video, video_id=video_id) | |
+ get_object_or_404(models.Video, video_id=video_id) | |
context['widget_params'] = json.dumps(config) | |
general_settings = {} | |
@@ -157,7 +165,6 @@ def widget_demo(request): | |
context['help_mode'] = True | |
else: | |
context['help_mode'] = False | |
- spaces = ' ' * 9 | |
params = base_widget_params(request) | |
context['embed_js_url'] = \ | |
"http://{0}/embed{1}.js".format( | |
diff --git a/media/js/unisubs.js b/media/js/unisubs.js | |
index e9e5860..c4aa4ba 100644 | |
--- a/media/js/unisubs.js | |
+++ b/media/js/unisubs.js | |
@@ -54,6 +54,21 @@ unisubs.currentUsername = null; | |
unisubs.returnURL = null; | |
/** | |
+ * @type {?object} | |
+ */ | |
+unisubs.guidelines = {}; | |
+ | |
+/** | |
+ * @type {?string} | |
+ */ | |
+unisubs.team_url = ''; | |
+ | |
+/** | |
+ * @type {?object} | |
+ */ | |
+unisubs.mode = null; | |
+ | |
+/** | |
* Current version of embed code. Set when widget gets inital | |
* state from server. Corresponds to value in settings.EMBED_JS_VERSION | |
* in Django settings.py file. | |
diff --git a/media/js/widget/api/api.js b/media/js/widget/api/api.js | |
index 443b424..e09e23b 100644 | |
--- a/media/js/widget/api/api.js | |
+++ b/media/js/widget/api/api.js | |
@@ -72,11 +72,18 @@ unisubs.api.openUnisubsDialogWithSettings = | |
unisubs.DEBUG = true; | |
} | |
unisubs.widget.WidgetController.makeGeneralSettings(generalSettings); | |
- if (config['returnURL']) | |
+ if (config['returnURL']) { | |
unisubs.returnURL = config['returnURL']; | |
+ } | |
if (config['guidelines']) { | |
unisubs.guidelines = config['guidelines']; | |
} | |
+ if (config['team_url']) { | |
+ unisubs.team_url = config['team_url']; | |
+ } | |
+ if (config['mode']) { | |
+ unisubs.mode = config['mode']; | |
+ } | |
unisubs.IS_NULL = !!config['nullWidget']; | |
var videoSource = | |
unisubs.player.MediaSource.videoSourceForURL( | |
diff --git a/media/js/widget/reviewsubtitles/dialog.js b/media/js/widget/reviewsubtitles/dialog.js | |
new file mode 100644 | |
index 0000000..0608649 | |
--- /dev/null | |
+++ b/media/js/widget/reviewsubtitles/dialog.js | |
@@ -0,0 +1,186 @@ | |
+// Universal Subtitles, universalsubtitles.org | |
+// | |
+// Copyright (C) 2011 Participatory Culture Foundation | |
+// | |
+// 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/agpl-3.0.html. | |
+ | |
+goog.provide('unisubs.reviewsubtitles.Dialog'); | |
+ | |
+/** | |
+ * @constructor | |
+ * | |
+ */ | |
+unisubs.reviewsubtitles.Dialog = function(videoSource, serverModel, | |
+ subtitleState) { | |
+ unisubs.Dialog.call(this, videoSource); | |
+ unisubs.SubTracker.getInstance().start(true); | |
+ | |
+ this.opener_ = opener; | |
+ this.subtitleState_ = subtitleState; | |
+ this.serverModel_ = serverModel; | |
+ this.captionSet_ = this.serverModel_.getCaptionSet(); | |
+ this.captionManager_ = new unisubs.CaptionManager(this.getVideoPlayerInternal(), this.captionSet_); | |
+ this.saved_ = false; | |
+}; | |
+goog.inherits(unisubs.reviewsubtitles.Dialog, unisubs.Dialog); | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.createDom = function() { | |
+ unisubs.reviewsubtitles.Dialog.superClass_.createDom.call(this); | |
+ this.reviewPanel_ = new unisubs.reviewsubtitles.ReviewSubtitlesPanel( | |
+ this.serverModel_.getCaptionSet(), this.getVideoPlayerInternal(), | |
+ this.serverModel_, this.captionManager_); | |
+ this.getCaptioningAreaInternal().addChild(this.reviewPanel_, true); | |
+ | |
+ var rightPanel = this.createRightPanel_(); | |
+ | |
+ this.setRightPanelInternal(rightPanel); | |
+ this.getHandler(). | |
+ listen( | |
+ rightPanel, unisubs.RightPanel.EventType.DONE, | |
+ this.handleDoneKeyPress_). | |
+ listen( | |
+ rightPanel, unisubs.RightPanel.EventType.SAVEANDEXIT, | |
+ this.handleSaveAndExitKeyPress_); | |
+ goog.dom.classes.add(this.getContentElement(), 'unisubs-modal-widget-translate'); | |
+ this.showGuidelines_(); | |
+ | |
+ this.timelineSubtitleSet_ = new unisubs.timeline.SubtitleSet(this.captionSet_, this.getVideoPlayerInternal()); | |
+ this.getTimelinePanelInternal().addChild( | |
+ new unisubs.timeline.Timeline( | |
+ 1, this.timelineSubtitleSet_, | |
+ this.getVideoPlayerInternal()), true); | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.showGuidelines_ = function() { | |
+ if (!unisubs.guidelines['review']) { | |
+ return; | |
+ } | |
+ | |
+ var guidelinesPanel = new unisubs.GuidelinesPanel(unisubs.guidelines['review']); | |
+ this.showTemporaryPanel(guidelinesPanel); | |
+ this.displayingGuidelines_ = true; | |
+ | |
+ var that = this; | |
+ this.getHandler().listenOnce(guidelinesPanel, unisubs.GuidelinesPanel.CONTINUE, function(e) { | |
+ goog.Timer.callOnce(function() { | |
+ that.displayingGuidelines_ = false; | |
+ that.hideTemporaryPanel(); | |
+ }); | |
+ }); | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.createRightPanel_ = function() { | |
+ var title = "Review Subtitles"; | |
+ var helpContents = new unisubs.RightPanel.HelpContents(title, ["Help goes here"]); | |
+ return new unisubs.reviewsubtitles.ReviewSubtitlesRightPanel(this.serverModel_, helpContents, [], false, "Done?", "Submit final Review"); | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.isWorkSaved = function() { | |
+ // TODO | |
+ return this.saved_ || !this.serverModel_.anySubtitlingWorkDone(); | |
+}; | |
+ | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.captionReached_ = function(event) { | |
+ var c = event.caption; | |
+ this.getVideoPlayerInternal().showCaptionText(c ? c.getText() : ''); | |
+}; | |
+unisubs.reviewsubtitles.Dialog.prototype.enterDocument = function() { | |
+ unisubs.reviewsubtitles.Dialog.superClass_.enterDocument.call(this); | |
+ unisubs.Dialog.translationDialogOpen = false; | |
+ var doc = this.getDomHelper().getDocument(); | |
+ this.getHandler().listen( | |
+ this.captionManager_, | |
+ unisubs.CaptionManager.CAPTION, | |
+ this.captionReached_); | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.handleApprove_ = function(e) { | |
+ e.preventDefault(); | |
+ this.saveWork(true); | |
+}; | |
+// unisubs.translate.Dialog.prototype.saveWorkInternal = function(closeAfterSave) { | |
+// var that = this; | |
+// this.getRightPanelInternal().showLoading(true); | |
+// this.serverModel_.finish( | |
+// function(serverMsg){ | |
+// unisubs.subtitle.OnSavedDialog.show(serverMsg, function(){ | |
+// that.onWorkSaved(closeAfterSave); | |
+// }) | |
+// }, | |
+// function(opt_status) { | |
+// if (that.finishFailDialog_) | |
+// that.finishFailDialog_.failedAgain(opt_status); | |
+// else | |
+// that.finishFailDialog_ = unisubs.finishfaildialog.Dialog.show( | |
+// that.serverModel_.getCaptionSet(), opt_status, | |
+// goog.bind(that.saveWorkInternal, that, closeAfterSave)); | |
+// }); | |
+// }; | |
+// unisubs.translate.Dialog.prototype.onWorkSaved = function() { | |
+// if (this.finishFailDialog_) { | |
+// this.finishFailDialog_.setVisible(false); | |
+// this.finishFailDialog_ = null; | |
+// } | |
+// unisubs.widget.ResumeEditingRecord.clear(); | |
+// this.getRightPanelInternal().showLoading(false); | |
+// this.saved_ = true; | |
+// this.setVisible(false); | |
+// } | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.saveWorkImpl_ = function(closeAfterSave, isComplete) { | |
+ this.getRightPanelInternal().showLoading(true); | |
+ | |
+ var that = this; | |
+ this.serverModel_.finish( | |
+ function(serverMsg){ | |
+ unisubs.subtitle.OnSavedDialog.show(serverMsg, function(){ | |
+ that.onWorkSaved(closeAfterSave, isComplete); | |
+ }); | |
+ }, | |
+ function(opt_status) { | |
+ if (that.finishFailDialog_) { | |
+ that.finishFailDialog_.failedAgain(opt_status); | |
+ } else { | |
+ that.finishFailDialog_ = unisubs.finishfaildialog.Dialog.show( | |
+ that.captionSet_, opt_status, | |
+ goog.bind(that.saveWorkImpl_, that, | |
+ closeAfterSave, isComplete)); | |
+ } | |
+ }, | |
+ function() { | |
+ that.doneButtonEnabled_ = true; | |
+ that.getRightPanelInternal().showLoading(false); | |
+ }); | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.disposeInternal = function() { | |
+ unisubs.reviewsubtitles.Dialog.superClass_.disposeInternal.call(this); | |
+ this.serverModel_.dispose(); | |
+ this.timelineSubtitleSet_.dispose(); | |
+ this.timelineSubtitleSet_ = null; | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.getSubtitleLanguage = function(){ | |
+ return this.subtitleState_.LANGUAGE; | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.getServerModel = function(){ | |
+ return this.serverModel_; | |
+}; | |
+ | |
+unisubs.reviewsubtitles.Dialog.prototype.makeJsonSubs = function () { | |
+ return this.serverModel_.getCaptionSet().makeJsonSubs(); | |
+}; | |
diff --git a/media/js/widget/reviewsubtitles/reviewsubtitlespanel.js b/media/js/widget/reviewsubtitles/reviewsubtitlespanel.js | |
new file mode 100644 | |
index 0000000..354ac51 | |
--- /dev/null | |
+++ b/media/js/widget/reviewsubtitles/reviewsubtitlespanel.js | |
@@ -0,0 +1,120 @@ | |
+// Universal Subtitles, universalsubtitles.org | |
+// | |
+// Copyright (C) 2010 Participatory Culture Foundation | |
+// | |
+// 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/agpl-3.0.html. | |
+ | |
+goog.provide('unisubs.reviewsubtitles.ReviewSubtitlesPanel'); | |
+ | |
+/** | |
+ * @constructor | |
+ * @param {unisubs.subtitle.EditableCaptionSet} subtitles The subtitles | |
+ * for the video, so far. | |
+ * @param {unisubs.player.AbstractVideoPlayer} videoPlayer | |
+ * @param {unisubs.CaptionManager} Caption manager, already containing subtitles | |
+ * with start_time set. | |
+ */ | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel = function(subtitles, videoPlayer, serverModel, captionManager) { | |
+ goog.ui.Component.call(this); | |
+ /** | |
+ * @type {unisubs.subtitle.EditableCaptionSet} | |
+ */ | |
+ this.subtitles_ = subtitles; | |
+ | |
+ this.videoPlayer_ = videoPlayer; | |
+ /** | |
+ * @protected | |
+ */ | |
+ this.serverModel = serverModel; | |
+ this.captionManager_ = captionManager; | |
+ this.videoStarted_ = false; | |
+ this.downSub_ = null; | |
+ this.downPlayheadTime_ = -1; | |
+}; | |
+goog.inherits(unisubs.reviewsubtitles.ReviewSubtitlesPanel, goog.ui.Component); | |
+ | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.enterDocument = function() { | |
+ unisubs.reviewsubtitles.ReviewSubtitlesPanel.superClass_.enterDocument.call(this); | |
+ var handler = this.getHandler(); | |
+ handler.listen(this.captionManager_, | |
+ unisubs.CaptionManager.CAPTION, | |
+ this.captionReached_) | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.createDom = function() { | |
+ unisubs.reviewsubtitles.ReviewSubtitlesPanel.superClass_.createDom.call(this); | |
+ var $d = goog.bind(this.getDomHelper().createDom, this.getDomHelper()); | |
+ this.getElement().appendChild(this.contentElem_ = $d('div')); | |
+ this.addChild(this.subtitleList_ = new unisubs.subtitle.SubtitleList( | |
+ this.videoPlayer_, this.subtitles_, true, false, true), true); | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.getRightPanel = function() { | |
+ if (!this.rightPanel_) { | |
+ this.rightPanel_ = this.createRightPanelInternal(); | |
+ } | |
+ return this.rightPanel_; | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.createRightPanelInternal = function() { | |
+ var helpContents = new unisubs.RightPanel.HelpContents( | |
+ "Syncing", | |
+ ["Congratulations, you finished the hard part (all that typing)!", | |
+ ["Now, to line up your subtitles to the video, tap the DOWN ARROW right ", | |
+ "when each subtitle should appear."].join(''), | |
+ "Tap DOWN to begin, tap it for the first subtitle, and so on.", | |
+ ["Don't worry about small mistakes. We can correct them in the ", | |
+ "next step. If you need to start over, click \"restart\" ", | |
+ "below."].join('')], | |
+ 3, 1); | |
+ var extraHelp = | |
+ ["Press play, then tap this button or the down arrow when the next subtitle should appear."]; | |
+ return new unisubs.RightPanel( | |
+ this.serverModel, helpContents, extraHelp, | |
+ this.makeKeySpecsInternal(), true, "Done?", | |
+ "Next Step: Reviewing"); | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.makeKeySpecsInternal = function() { | |
+ var KC = goog.events.KeyCodes; | |
+ return [ | |
+ new unisubs.RightPanel.KeySpec( | |
+ 'unisubs-begin', 'unisubs-down', 'down', | |
+ 'Tap when next subtitle should appear', KC.DOWN, 0), | |
+ new unisubs.RightPanel.KeySpec( | |
+ 'unisubs-play', 'unisubs-tab', 'tab', 'Play/Pause', KC.TAB, 0), | |
+ new unisubs.RightPanel.KeySpec( | |
+ 'unisubs-skip', 'unisubs-control', 'shift\n+\ntab', | |
+ 'Skip Back 8 Seconds', KC.TAB, | |
+ unisubs.RightPanel.KeySpec.Modifier.SHIFT) | |
+ ]; | |
+ | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.startOverClicked_ = function() { | |
+ var answer = | |
+ confirm("Are you sure you want to start over? All timestamps " + | |
+ "will be deleted."); | |
+ if (answer) { | |
+ this.subtitles_.clearTimes(); | |
+ this.videoPlayer_.setPlayheadTime(0); | |
+ } | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.captionReached_ = function(event) { | |
+ var editableCaption = event.caption; | |
+ this.subtitleList_.clearActiveWidget(); | |
+ if (editableCaption != null) | |
+ this.subtitleList_.setActiveWidget(editableCaption.getCaptionID()); | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesPanel.prototype.disposeInternal = function() { | |
+ unisubs.reviewsubtitles.ReviewSubtitlesPanel.superClass_.disposeInternal.call(this); | |
+ if (this.rightPanel_) | |
+ this.rightPanel_.dispose(); | |
+}; | |
diff --git a/media/js/widget/reviewsubtitles/reviewsubtitlesrightpanel.js b/media/js/widget/reviewsubtitles/reviewsubtitlesrightpanel.js | |
new file mode 100644 | |
index 0000000..234ba47 | |
--- /dev/null | |
+++ b/media/js/widget/reviewsubtitles/reviewsubtitlesrightpanel.js | |
@@ -0,0 +1,88 @@ | |
+// Universal Subtitles, universalsubtitles.org | |
+// | |
+// Copyright (C) 2011 Participatory Culture Foundation | |
+// | |
+// 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/agpl-3.0.html. | |
+ | |
+goog.provide('unisubs.reviewsubtitles.ReviewSubtitlesRightPanel'); | |
+ | |
+/** | |
+ * @constructor | |
+ * @extends unisubs.RightPanel | |
+ */ | |
+unisubs.reviewsubtitles.ReviewSubtitlesRightPanel = function(serverModel, | |
+ helpContents, | |
+ legendKeySpecs, | |
+ showRestart, | |
+ doneStrongText, | |
+ doneText) { | |
+ unisubs.RightPanel.call(this, serverModel, helpContents, null, | |
+ legendKeySpecs, showRestart, doneStrongText, doneText); | |
+ | |
+ this.showSaveExit = false; | |
+ this.showDoneButton = false; | |
+}; | |
+goog.inherits(unisubs.reviewsubtitles.ReviewSubtitlesRightPanel, unisubs.RightPanel); | |
+ | |
+unisubs.reviewsubtitles.ReviewSubtitlesRightPanel.prototype.appendMiddleContentsInternal = function($d, el) { | |
+ el.appendChild($d('label', {'class': 'unisubs-review-notes-label', 'for': 'unisubs-review-notes'}, 'Notes')); | |
+ el.appendChild($d('textarea', {'class': 'unisubs-review-notes', 'id': 'unisubs-review-notes', 'name': 'notes'})); | |
+ el.appendChild($d('hr')); | |
+ | |
+ this.reassignLink_ = $d('a', {'href': unisubs.team_url}, 'reassign this task'); | |
+ this.editedVersionLink_ = $d('a', {'href': '#'}, 'submit an edited version'); | |
+ | |
+ el.appendChild($d('p', null, | |
+ 'You can also ', | |
+ this.reassignLink_, | |
+ ' to someone else, or ', | |
+ this.editedVersionLink_, | |
+ ' yourself.', | |
+ ' If you submit a new version it will also be subject to review.' | |
+ )); | |
+ | |
+ var handler = this.getHandler(); | |
+ handler.listen(this.reassignLink_, 'click', this.reassignLinkClicked_); | |
+ handler.listen(this.editedVersionLink_, 'click', this.editedVersionLinkClicked_); | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesRightPanel.prototype.appendCustomButtonsInternal = function($d, el) { | |
+ this.approveButton_ = $d('a', {'class': 'unisubs-done'}, 'Approve'); | |
+ this.sendBackButton_ = $d('a', {'class': 'unisubs-done'}, 'Send Back'); | |
+ | |
+ el.appendChild(this.sendBackButton_); | |
+ el.appendChild(this.approveButton_); | |
+ | |
+ var handler = this.getHandler(); | |
+ handler.listen(this.approveButton_, 'click', this.approveButtonClicked_); | |
+ handler.listen(this.sendBackButton_, 'click', this.sendBackButtonClicked_); | |
+}; | |
+ | |
+unisubs.reviewsubtitles.ReviewSubtitlesRightPanel.prototype.approveButtonClicked_ = function(e){ | |
+ e.preventDefault(); | |
+ | |
+ alert("o hai"); | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesRightPanel.prototype.sendBackButtonClicked_ = function(e){ | |
+ e.preventDefault(); | |
+ | |
+ alert("o hai"); | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesRightPanel.prototype.reassignLinkClicked_ = function(e){ | |
+}; | |
+unisubs.reviewsubtitles.ReviewSubtitlesRightPanel.prototype.editedVersionLinkClicked_ = function(e){ | |
+ e.preventDefault(); | |
+ | |
+ alert("o hai"); | |
+}; | |
diff --git a/media/js/widget/rightpanel.js b/media/js/widget/rightpanel.js | |
index e3dba32..8aa4899 100644 | |
--- a/media/js/widget/rightpanel.js | |
+++ b/media/js/widget/rightpanel.js | |
@@ -59,6 +59,15 @@ unisubs.RightPanel = function(serverModel, | |
this.showSaveExit = true; | |
/** | |
+ * Whether to show the "Done? ... >" button. Should be overridden by sub | |
+ * classes as needed. | |
+ * | |
+ * @protected | |
+ * @type {boolean} | |
+ */ | |
+ this.showDoneButton = true; | |
+ | |
+ /** | |
* Non-null iff the mouse has just been pressed on one of the legend keys | |
* and not released or moved away from the legend key yet. | |
* @type {?string} | |
@@ -211,6 +220,9 @@ unisubs.RightPanel.prototype.appendLegendClearInternal = function($d, legendDiv) | |
unisubs.RightPanel.prototype.appendMiddleContentsInternal = function($d, el) { | |
// dear subclasses, override me if you want. love, rightpanel. | |
}; | |
+unisubs.RightPanel.prototype.appendCustomButtonsInternal = function($d, el) { | |
+ // dear subclasses, override me if you want. love, rightpanel. | |
+}; | |
unisubs.RightPanel.prototype.appendStepsContents_ = function($d, el) { | |
this.loginDiv_ = $d('div'); | |
this.loadingGif_ = $d('img', | |
@@ -248,7 +260,12 @@ unisubs.RightPanel.prototype.appendStepsContents_ = function($d, el) { | |
this.getHandler().listen( | |
this.downloadLink_, 'click', this.downloadClicked_); | |
- goog.dom.append(stepsDiv, this.doneAnchor_); | |
+ this.appendCustomButtonsInternal($d, el); | |
+ | |
+ if (this.showDoneButton) { | |
+ goog.dom.append(stepsDiv, this.doneAnchor_); | |
+ this.getHandler().listen(this.doneAnchor_, 'click', this.doneClicked_); | |
+ } | |
if (this.showSaveExit) { | |
var saveAndExitAnchor = $d( | |
@@ -263,7 +280,6 @@ unisubs.RightPanel.prototype.appendStepsContents_ = function($d, el) { | |
} | |
goog.dom.append(el, stepsDiv); | |
- this.getHandler().listen(this.doneAnchor_, 'click', this.doneClicked_); | |
this.updateLoginState(); | |
}; | |
unisubs.RightPanel.prototype.legendKeyClicked_ = function(keyCode, modifiers, event) { | |
diff --git a/media/js/widget/subtitle/addsubtitlewidget.js b/media/js/widget/subtitle/addsubtitlewidget.js | |
index d68f1cf..8c31fa8 100644 | |
--- a/media/js/widget/subtitle/addsubtitlewidget.js | |
+++ b/media/js/widget/subtitle/addsubtitlewidget.js | |
@@ -23,7 +23,6 @@ goog.provide('unisubs.subtitle.AddSubtitleWidget'); | |
*/ | |
unisubs.subtitle.AddSubtitleWidget = function() { | |
goog.ui.Component.call(this); | |
- | |
}; | |
goog.inherits(unisubs.subtitle.AddSubtitleWidget, goog.ui.Component); | |
diff --git a/media/js/widget/subtitle/editrightpanel.js b/media/js/widget/subtitle/editrightpanel.js | |
index 5f768a3..07976b8 100644 | |
--- a/media/js/widget/subtitle/editrightpanel.js | |
+++ b/media/js/widget/subtitle/editrightpanel.js | |
@@ -34,6 +34,23 @@ unisubs.subtitle.EditRightPanel = function(serverModel, | |
doneText); | |
}; | |
goog.inherits(unisubs.subtitle.EditRightPanel, unisubs.RightPanel); | |
+ | |
+unisubs.subtitle.EditRightPanel.prototype.appendHelpContentsInternal = function($d, el) { | |
+ var backLink = $d('a', {'href': '#'}, 'click here'); | |
+ this.getHandler().listenOnce( | |
+ backLink, 'click', this.backClickedInternal); | |
+ var helpDiv = $d('div', 'unisubs-help-heading', | |
+ $d('h2', null, "EDIT: Edit existing subtitles")); | |
+ el.appendChild(helpDiv); | |
+ el.appendChild($d('p', null, | |
+ goog.dom.createTextNode( | |
+ 'Double click on any subtitle to edit its text. To add more text, '), | |
+ backLink, | |
+ goog.dom.createTextNode(' for TYPING mode.'))); | |
+ el.appendChild($d('p', null, 'Adjust subtitle timing by dragging their edges in the timeline to the left and watching the results.')); | |
+ el.appendChild($d('p', null, 'You can also edit timing by rolling over any timestamp, and clicking the left/right buttons that appear. After you click, your change will play back.')); | |
+ el.appendChild($d('p', null, 'Hitting the DOWN ARROW will set the start of the next subtitle.')); | |
+}; | |
unisubs.subtitle.EditRightPanel.prototype.appendHelpContentsInternal = function($d, el) { | |
var backLink = $d('a', {'href': '#'}, 'click here'); | |
this.getHandler().listenOnce( | |
diff --git a/media/js/widget/subtitle/reviewrightpanel.js b/media/js/widget/subtitle/reviewrightpanel.js | |
index 747327d..11bc462 100644 | |
--- a/media/js/widget/subtitle/reviewrightpanel.js | |
+++ b/media/js/widget/subtitle/reviewrightpanel.js | |
@@ -22,12 +22,12 @@ goog.provide('unisubs.subtitle.ReviewRightPanel'); | |
* @extends unisubs.RightPanel | |
*/ | |
unisubs.subtitle.ReviewRightPanel = function(serverModel, | |
- helpContents, | |
- extraHelp, | |
- legendKeySpecs, | |
- showRestart, | |
- doneStrongText, | |
- doneText) { | |
+ helpContents, | |
+ extraHelp, | |
+ legendKeySpecs, | |
+ showRestart, | |
+ doneStrongText, | |
+ doneText) { | |
unisubs.RightPanel.call(this, serverModel, helpContents, extraHelp, | |
legendKeySpecs, | |
showRestart, doneStrongText, doneText); | |
diff --git a/media/js/widget/subtitle/subtitlelist.js b/media/js/widget/subtitle/subtitlelist.js | |
index 8336c54..5022c38 100644 | |
--- a/media/js/widget/subtitle/subtitlelist.js | |
+++ b/media/js/widget/subtitle/subtitlelist.js | |
@@ -24,10 +24,12 @@ goog.provide('unisubs.subtitle.SubtitleList'); | |
* @param {unisubs.subtitle.EditableCaptionSet} captionSet | |
*/ | |
unisubs.subtitle.SubtitleList = function(videoPlayer, captionSet, | |
- displayTimes, opt_showBeginMessage) { | |
+ displayTimes, opt_showBeginMessage, | |
+ readOnly) { | |
goog.ui.Component.call(this); | |
this.videoPlayer_ = videoPlayer; | |
this.captionSet_ = captionSet; | |
+ this.readOnly_ = readOnly; | |
this.displayTimes_ = displayTimes; | |
this.currentActiveSubtitle_ = null; | |
/** | |
@@ -49,8 +51,14 @@ unisubs.subtitle.SubtitleList.prototype.createDom = function() { | |
var dh = this.getDomHelper(); | |
var $d = goog.bind(dh.createDom, dh); | |
var $t = goog.bind(dh.createTextNode, dh); | |
- this.setElementInternal($d('ul', 'unisubs-titlesList')); | |
- if (this.captionSet_.count() == 0 && this.showBeginMessage_) { | |
+ | |
+ var list_class = 'unisubs-titlesList'; | |
+ if (this.readOnly_) { | |
+ list_class += ' read-only'; | |
+ } | |
+ this.setElementInternal($d('ul', list_class)); | |
+ | |
+ if (this.captionSet_.count() === 0 && this.showBeginMessage_) { | |
this.showingBeginMessage_ = true; | |
goog.dom.classes.add(this.getElement(), 'unisubs-beginTab'); | |
this.getElement().appendChild( | |
@@ -58,9 +66,8 @@ unisubs.subtitle.SubtitleList.prototype.createDom = function() { | |
$t('To begin, press TAB to play'), | |
$d('br'), | |
$t('and start typing!'))); | |
- } | |
- else { | |
- this.addAddButton_(); | |
+ } else { | |
+ this.readOnly_ || this.addAddButton_(); | |
var i; | |
for (i = 0; i < this.captionSet_.count(); i++) | |
this.addSubtitle(this.captionSet_.caption(i), false, true); | |
@@ -107,8 +114,9 @@ unisubs.subtitle.SubtitleList.prototype.enterDocument = function() { | |
this.captionSet_, | |
et.DELETE, | |
this.captionDeleted_); | |
- if (this.addSubtitleButton_) | |
+ if (this.addSubtitleButton_ && !this.readOnly_) { | |
this.listenForAdd_(); | |
+ } | |
}; | |
unisubs.subtitle.SubtitleList.prototype.captionsCleared_ = function(event) { | |
this.subtitleMap_ = {}; | |
@@ -131,7 +139,8 @@ unisubs.subtitle.SubtitleList.prototype.createNewSubWidget_ = | |
editableCaption, | |
this.captionSet_, | |
goog.bind(this.setCurrentlyEditing_, this), | |
- this.displayTimes_); | |
+ this.displayTimes_, | |
+ this.readOnly_); | |
}; | |
/** | |
* | |
@@ -145,10 +154,11 @@ unisubs.subtitle.SubtitleList.prototype.addSubtitle = | |
goog.dom.removeChildren(this.getElement()); | |
goog.dom.classes.remove(this.getElement(), 'unisubs-beginTab'); | |
this.showingBeginMessage_ = false; | |
- this.addAddButton_(); | |
+ this.readOnly_ || this.addAddButton_(); | |
} | |
+ var dest_offset = this.getChildCount() - (this.readOnly_ ? 0 : 1); | |
var subtitleWidget = this.createNewSubWidget_(subtitle); | |
- this.addChildAt(subtitleWidget, this.getChildCount() - 1, true); | |
+ this.addChildAt(subtitleWidget, dest_offset, true); | |
this.subtitleMap_[subtitle.getCaptionID()] = subtitleWidget; | |
if (opt_scrollDown && typeof(opt_scrollDown) == 'boolean') | |
this.scrollToCaption(subtitle.getCaptionID()); | |
@@ -177,7 +187,7 @@ unisubs.subtitle.SubtitleList.prototype.setLastSub_ = function() { | |
if (subWidget == this.lastSub_) | |
return; | |
this.lastSubMouseHandler_.removeAll(); | |
- if (subWidget != null) { | |
+ if (subWidget != null && !this.readOnly_) { | |
var et = goog.events.EventType; | |
this.lastSubMouseHandler_. | |
listen(subWidget.getElement(), | |
diff --git a/media/js/widget/subtitle/subtitlewidget.js b/media/js/widget/subtitle/subtitlewidget.js | |
index 40aa9c6..5d8cc2b 100644 | |
--- a/media/js/widget/subtitle/subtitlewidget.js | |
+++ b/media/js/widget/subtitle/subtitlewidget.js | |
@@ -30,7 +30,8 @@ goog.provide('unisubs.subtitle.SubtitleWidget'); | |
unisubs.subtitle.SubtitleWidget = function(subtitle, | |
subtitleSet, | |
editingFn, | |
- displayTimes) { | |
+ displayTimes, | |
+ readOnly) { | |
goog.ui.Component.call(this); | |
this.subtitle_ = subtitle; | |
this.subtitleSet_ = subtitleSet; | |
@@ -38,6 +39,7 @@ unisubs.subtitle.SubtitleWidget = function(subtitle, | |
this.displayTimes_ = displayTimes; | |
this.keyHandler_ = null; | |
this.timeSpinner_ = null; | |
+ this.readOnly_ = readOnly; | |
this.insertDeleteButtonsShowing_ = false; | |
}; | |
goog.inherits(unisubs.subtitle.SubtitleWidget, goog.ui.Component); | |
@@ -47,20 +49,31 @@ unisubs.subtitle.SubtitleWidget.prototype.getContentElement = function() { | |
}; | |
unisubs.subtitle.SubtitleWidget.prototype.createDom = function() { | |
var $d = goog.bind(this.getDomHelper().createDom, this.getDomHelper()); | |
- this.deleteButton_ = this.createDeleteButton_($d); | |
- this.insertButton_ = this.createInsertButton_($d); | |
- goog.style.showElement(this.deleteButton_, false); | |
- goog.style.showElement(this.insertButton_, false); | |
+ if (!this.readOnly_) { | |
+ this.deleteButton_ = this.createDeleteButton_($d); | |
+ this.insertButton_ = this.createInsertButton_($d); | |
+ goog.style.showElement(this.deleteButton_, false); | |
+ goog.style.showElement(this.insertButton_, false); | |
+ | |
+ this.setElementInternal( | |
+ $d('li', null, | |
+ this.contentElement_, | |
+ this.titleElem_ = | |
+ $d('span', {'className':'unisubs-title'}, | |
+ this.titleElemInner_ = | |
+ $d('span')), | |
+ this.deleteButton_, | |
+ this.insertButton_)); | |
+ } else { | |
+ this.setElementInternal( | |
+ $d('li', null, | |
+ this.contentElement_, | |
+ this.titleElem_ = | |
+ $d('span', {'className':'unisubs-title'}, | |
+ this.titleElemInner_ = | |
+ $d('span')))); | |
+ } | |
this.contentElement_ = $d('span', 'unisubs-timestamp'); | |
- this.setElementInternal( | |
- $d('li', null, | |
- this.contentElement_, | |
- this.titleElem_ = | |
- $d('span', {'className':'unisubs-title'}, | |
- this.titleElemInner_ = | |
- $d('span')), | |
- this.deleteButton_, | |
- this.insertButton_)); | |
if (!this.displayTimes_) { | |
goog.dom.classes.add(this.titleElem_, 'unisubs-title-notime'); | |
unisubs.style.showElement(this.contentElement_, false); | |
@@ -89,17 +102,19 @@ unisubs.subtitle.SubtitleWidget.prototype.createInsertButton_ = function($d) { | |
unisubs.subtitle.SubtitleWidget.prototype.enterDocument = function() { | |
unisubs.subtitle.SubtitleWidget.superClass_.enterDocument.call(this); | |
var et = goog.events.EventType; | |
- this.getHandler(). | |
- listen( | |
- this.subtitle_, | |
- unisubs.subtitle.EditableCaption.CHANGE, | |
- this.updateValues_). | |
- listen(this.titleElem_, et.CLICK, this.clicked_). | |
- listen(this.getElement(), | |
- [et.MOUSEOVER, et.MOUSEOUT], | |
- this.mouseOverOut_). | |
- listen(this.deleteButton_, et.CLICK, this.deleteClicked_). | |
- listen(this.insertButton_, et.CLICK, this.insertClicked_); | |
+ | |
+ if (!this.readOnly_) { | |
+ this.getHandler().listen(this.deleteButton_, et.CLICK, this.deleteClicked_) | |
+ .listen(this.insertButton_, et.CLICK, this.insertClicked_) | |
+ .listen(this.titleElem_, et.CLICK, this.clicked_) | |
+ .listen(this.getElement(), | |
+ [et.MOUSEOVER, et.MOUSEOUT], | |
+ this.mouseOverOut_) | |
+ .listen(this.subtitle_, | |
+ unisubs.subtitle.EditableCaption.CHANGE, | |
+ this.updateValues_); | |
+ } | |
+ | |
if (this.timeSpinner_) | |
this.getHandler().listen( | |
this.timeSpinner_, | |
@@ -155,8 +170,10 @@ unisubs.subtitle.SubtitleWidget.prototype.showInsertDeleteButtons_ = | |
return; | |
this.insertDeleteButtonsShowing_ = show; | |
- goog.style.showElement(this.deleteButton_, show); | |
- goog.style.showElement(this.insertButton_, show); | |
+ if (!this.readOnly_) { | |
+ goog.style.showElement(this.deleteButton_, show); | |
+ goog.style.showElement(this.insertButton_, show); | |
+ } | |
}; | |
unisubs.subtitle.SubtitleWidget.prototype.clicked_ = function(event) { | |
if (this.showingTextarea_) | |
diff --git a/media/js/widget/subtitle/syncpanel.js b/media/js/widget/subtitle/syncpanel.js | |
index 8ca2dda..1b69069 100644 | |
--- a/media/js/widget/subtitle/syncpanel.js | |
+++ b/media/js/widget/subtitle/syncpanel.js | |
@@ -62,7 +62,7 @@ unisubs.subtitle.SyncPanel.prototype.createDom = function() { | |
var $d = goog.bind(this.getDomHelper().createDom, this.getDomHelper()); | |
this.getElement().appendChild(this.contentElem_ = $d('div')); | |
this.addChild(this.subtitleList_ = new unisubs.subtitle.SubtitleList( | |
- this.videoPlayer_, this.subtitles_, true), true); | |
+ this.videoPlayer_, this.subtitles_, true, false, false), true); | |
}; | |
unisubs.subtitle.SyncPanel.prototype.getRightPanel = function() { | |
if (!this.rightPanel_) { | |
@@ -115,9 +115,7 @@ unisubs.subtitle.SyncPanel.prototype.makeKeySpecsInternal = function() { | |
unisubs.subtitle.SyncPanel.prototype.suspendKeyEvents = function(suspended) { | |
this.keyEventsSuspended_ = suspended; | |
}; | |
-unisubs.subtitle.SyncPanel.prototype.handleLegendKeyPress_ = | |
- function(event) | |
-{ | |
+unisubs.subtitle.SyncPanel.prototype.handleLegendKeyPress_ = function(event) { | |
if (event.keyCode == goog.events.KeyCodes.DOWN) { | |
if (event.keyEventType == goog.events.EventType.MOUSEDOWN && | |
!this.currentlyEditingSubtitle_()) | |
diff --git a/media/js/widget/subtitle/transcribepanel.js b/media/js/widget/subtitle/transcribepanel.js | |
index 68f11a6..b2c7a5a 100644 | |
--- a/media/js/widget/subtitle/transcribepanel.js | |
+++ b/media/js/widget/subtitle/transcribepanel.js | |
@@ -68,7 +68,7 @@ unisubs.subtitle.TranscribePanel.prototype.addElems_ = function(el) { | |
this.addChild(this.lineEntry_ = new unisubs.subtitle.TranscribeEntry( | |
this.videoPlayer_), true); | |
this.addChild(this.subtitleList_ = new unisubs.subtitle.SubtitleList( | |
- this.videoPlayer_, this.captionSet_, false, true), true); | |
+ this.videoPlayer_, this.captionSet_, false, true, false), true); | |
this.setPlayMode(unisubs.UserSettings.getStringValue( | |
unisubs.UserSettings.Settings.VIDEO_SPEED_MODE) || | |
unisubs.subtitle.TranscribePanel.PlayMode.PLAY_STOP); | |
diff --git a/media/js/widget/subtitledialogopener.js b/media/js/widget/subtitledialogopener.js | |
index d62b21e..4f53542 100644 | |
--- a/media/js/widget/subtitledialogopener.js | |
+++ b/media/js/widget/subtitledialogopener.js | |
@@ -241,9 +241,11 @@ unisubs.widget.SubtitleDialogOpener.prototype.startEditingResponseHandler_ = | |
} | |
var serverModel = new unisubs.subtitle.MSServerModel( | |
sessionPK, this.videoID_, this.videoURL_, captionSet); | |
- if (subtitles.IS_ORIGINAL || subtitles.FORKED) | |
+ if (unisubs.mode == 'review') { | |
+ this.openSubtitleReviewingDialog(serverModel, subtitles); | |
+ } else if (subtitles.IS_ORIGINAL || subtitles.FORKED) { | |
this.openSubtitlingDialog(serverModel, subtitles); | |
- else { | |
+ } else { | |
this.openDependentTranslationDialog_( | |
serverModel, subtitles, originalSubtitles); | |
} | |
@@ -258,6 +260,16 @@ unisubs.widget.SubtitleDialogOpener.prototype.startEditingResponseHandler_ = | |
} | |
}; | |
+unisubs.widget.SubtitleDialogOpener.prototype.openSubtitleReviewingDialog = | |
+ function(serverModel, subtitleState) | |
+{ | |
+ this.subOpenFn_ && this.subOpenFn_(); | |
+ var subReviewDialog = new unisubs.reviewsubtitles.Dialog(this.videoSource_, serverModel, subtitleState); | |
+ | |
+ subReviewDialog.setParentEventTarget(this); | |
+ subReviewDialog.setVisible(true); | |
+}; | |
+ | |
unisubs.widget.SubtitleDialogOpener.prototype.openSubtitlingDialog = | |
function(serverModel, subtitleState) | |
{ | |
diff --git a/media/js/widget/subtitlestate.js b/media/js/widget/subtitlestate.js | |
index a6b35f7..4c7fb59 100644 | |
--- a/media/js/widget/subtitlestate.js | |
+++ b/media/js/widget/subtitlestate.js | |
@@ -30,6 +30,8 @@ unisubs.widget.SubtitleState = function(json, opt_subs) { | |
this.LANGUAGE_PK = json['language_pk']; | |
this.IS_ORIGINAL = json['is_original']; | |
this.IS_COMPLETE = json['is_complete']; | |
+ this.MODE = json['mode']; | |
+ | |
/** | |
* @type {number} | |
*/ | |
diff --git a/settings.py b/settings.py | |
index 56b2755..34c53b9 100644 | |
--- a/settings.py | |
+++ b/settings.py | |
@@ -261,6 +261,9 @@ JS_DIALOG = \ | |
'js/finishfaildialog/errorpanel.js', | |
'js/finishfaildialog/reattemptuploadpanel.js', | |
'js/finishfaildialog/copydialog.js', | |
+ 'js/widget/reviewsubtitles/dialog.js', | |
+ 'js/widget/reviewsubtitles/reviewsubtitlespanel.js', | |
+ 'js/widget/reviewsubtitles/reviewsubtitlesrightpanel.js', | |
'js/widget/subtitle/dialog.js', | |
'js/widget/subtitle/msservermodel.js', | |
'js/widget/subtitle/subtitlewidget.js', |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment