diff --git a/CHANGELOG.md b/CHANGELOG.md index f98c1ea68..7dd823202 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +# WIP + +* links + * create links in your drive or a team drive + * share with contacts + * when you receive a link, you can "open", "store", "decide later" or dismiss from the notification dropdown + * share with a team (the link is instantly added to the team) + * store in your own drive from your team drive + * embed a link into a pad + * And you can have multiple links to the same target in one drive +* tabs in ckeditor +* fix recognition of premium user tickets in the admin support panel +* forms + * disable usage of the indexedDB cache for form results + * handle empty messages + * fix initial title with form templates + * style improvements + * guard against a typeError with dates + * in the responses page you can click on a user in the polls to get this user's answers to the other questions + * unregistered users can set their username when they don't want to answer anonymously + * improve CSV export with polls + * decrement max choices when it exceeds the number of available options +* remove unused images +* drive + * show the bread-crumb and disable the tree in anon drives + # 4.8.0 ## Goals diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 6114884b2..8b01ad652 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -3048,6 +3048,7 @@ define([ var buttons = [{ name: Messages.friendRequest_later, onClick: function () { + // XXX feedback if (clicked) { return true; } clicked = true; }, @@ -3056,6 +3057,7 @@ define([ className: 'primary', name: Messages.link_open, onClick: function () { + // XXX feedback if (clicked) { return true; } clicked = true; common.openUnsafeURL(url); @@ -3067,6 +3069,7 @@ define([ onClick: function () { if (clicked) { return; } clicked = true; + // XXX feedback common.getSframeChannel().query("Q_DRIVE_USEROBJECT", { cmd: "addLink", data: { diff --git a/www/common/common-util.js b/www/common/common-util.js index 1fd78cec1..ac50a1f24 100644 --- a/www/common/common-util.js +++ b/www/common/common-util.js @@ -161,6 +161,10 @@ }; }; + Util.inc = function (map, key, val) { + map[key] = (map[key] || 0) + (typeof(val) === 'number'? val: 1); + }; + Util.find = function (map, path) { var l = path.length; for (var i = 0; i < l; i++) { diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index cd456fd41..12c4431c8 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -42,8 +42,8 @@ define([ Pages) { - Messages.fm_link = "Link"; // XXX "New Link" ? - // XXX check for all occurrences of `fm_link` before changing it + Messages.fm_link_new = "New Link"; // XXX + Messages.fm_link_type = "Link"; // XXX var APP = window.APP = { editable: false, @@ -450,7 +450,7 @@ define([ 'tabindex': '-1', 'data-icon': AppConfig.applicationsIcon.link, 'data-type': 'link' - }, Messages.fm_link)), + }, Messages.fm_link_new)), ]), ]), $separator.clone()[0], @@ -1925,10 +1925,14 @@ define([ var $name = $('', {'class': 'cp-app-drive-element-name'}).text(name); $element.append($name); if (getViewMode() === 'grid') { - $element.attr('title', name); // XXX Util.fixHTML + //console.error(name, Util.fixHTML(name)); + // this is only safe because our build of tippy sets titles as + // 'textContent' instead of innerHTML, otherwise + // we would need to use Util.fixHTML + $element.attr('title', name); } - var type = Messages.fm_link; // XXX new translation key ("Link") + var type = Messages.fm_link_type; var $type = $('', { 'class': 'cp-app-drive-element-type cp-app-drive-element-list' }).text(type); @@ -1939,6 +1943,7 @@ define([ 'class': 'cp-app-drive-element-ctime cp-app-drive-element-list' }).text(getDate(data.ctime)); $element.append($type).append($adate).append($cdate); + // XXX feedback }; var _addOwnership = function ($span, $state, data) { if (data && Array.isArray(data.owners) && data.owners.indexOf(edPublic) !== -1) { @@ -2733,8 +2738,8 @@ define([ }; var showLinkModal = function () { Messages.fm_link_name = "Link name"; // XXX - Messages.fm_link_url = "URL"; - Messages.fm_link_warning = "Warning: URL size..."; + Messages.fm_link_url = "URL"; // XXX + Messages.fm_link_warning = "Warning: URL size..."; // XXX var name, url; var warning = h('div.alert.alert-warning', [ h('i.fa.fa-exclamation-triangle'), @@ -2780,6 +2785,7 @@ define([ name: n, url: u }, refresh); + // XXX feedback }, keys: [13] }); @@ -2863,7 +2869,7 @@ define([ options.push({ tag: 'a', attributes: {'class': 'cp-app-drive-new-link'}, - content: $('
').append(getIcon('link')).html() + Messages.fm_link + content: $('
').append(getIcon('link')).html() + Messages.fm_link_new }); options.push({tag: 'hr'}); } @@ -3188,7 +3194,7 @@ define([ 'cp-app-drive-element-grid' }).prepend(getIcon('link')).appendTo($container); $elementLink.append($('', {'class': 'cp-app-drive-new-name'}) - .text(Messages.fm_link)); + .text(Messages.fm_link_type)); } // Pads getNewPadTypes().forEach(function (type) { diff --git a/www/common/inner/share.js b/www/common/inner/share.js index 5225ea818..125dcb5e2 100644 --- a/www/common/inner/share.js +++ b/www/common/inner/share.js @@ -111,6 +111,7 @@ define([ if (mailbox) { // Friend if (friends[curve] && !mailbox.notifications) { return; } if (mailbox.notifications && mailbox.curvePublic) { + // XXX feedback common.mailbox.sendTo("SHARE_PAD", { href: href, isStatic: Boolean(config.static), diff --git a/www/common/notifications.js b/www/common/notifications.js index 24458420e..78c29b90f 100644 --- a/www/common/notifications.js +++ b/www/common/notifications.js @@ -115,6 +115,7 @@ define([ }; content.handler = function() { if (msg.content.isStatic) { + // XXX feedback UIElements.displayOpenLinkModal(common, { curve: msg.author, href: msg.content.href, diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 6aacd4a1b..d8e558dad 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -2058,8 +2058,17 @@ define([ } catch (e) { console.error(e); } + // Tell all the owners that the pad was deleted from the server - var curvePublic = store.proxy.curvePublic; + var curvePublic; + try { + // users in noDrive mode don't have a proxy and + // unregistered users don't have a curvePublic + curvePublic = store.proxy.curvePublic; + } catch (err) { + console.error(err); + return; + } m.forEach(function (obj) { var mb = JSON.parse(obj); if (mb.curvePublic === curvePublic) { return; } diff --git a/www/common/proxy-manager.js b/www/common/proxy-manager.js index 01c22812c..78196cf7c 100644 --- a/www/common/proxy-manager.js +++ b/www/common/proxy-manager.js @@ -1263,7 +1263,10 @@ define([ Array.prototype.push.apply(result, sfChannels); } - return result; + return result.filter(function (channel) { + if (typeof(channel) !== 'string') { return; } + return [32, 48].indexOf(channel.length) !== -1; + }); }; var addPad = function (Env, path, pad, cb) { diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index a532863a2..575971368 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -2003,6 +2003,8 @@ define([ sframeChan.on('EV_BURN_AFTER_READING', function () { startRealtime(); + // feedback fails for users in noDrive mode + Utils.Feedback.send("BURN_AFTER_READING", Boolean(cfg.noDrive)); }); sframeChan.ready(); diff --git a/www/common/toolbar.js b/www/common/toolbar.js index 785d1bc7e..5b53aa9a1 100644 --- a/www/common/toolbar.js +++ b/www/common/toolbar.js @@ -867,10 +867,6 @@ MessengerUI, Messages, Pages) { 'class': "cp-toolbar-link-logo" }).append(UIElements.getSvgLogo()); - /*.append($('', { - //src: '/customize/images/logo_white.png?' + ApiConfig.requireConf.urlArgs - src: '/customize/favicon/main-favicon.png?' + ApiConfig.requireConf.urlArgs - }));*/ var onClick = function (e) { e.preventDefault(); if (e.ctrlKey) { diff --git a/www/common/translations/messages.ja.json b/www/common/translations/messages.ja.json index 742a137d6..bab839f09 100644 --- a/www/common/translations/messages.ja.json +++ b/www/common/translations/messages.ja.json @@ -1,7 +1,7 @@ { "common_connectionLost": "サーバーとの接続が切断しました
再接続するまで閲覧モードになります。", "button_newsheet": "新規スプレッドシート", - "button_newkanban": "新規のカンバン", + "button_newkanban": "新規カンバン", "button_newwhiteboard": "新規ホワイトボード", "button_newslide": "新規プレゼンテーション", "button_newpoll": "新規投票・アンケート", @@ -111,7 +111,7 @@ "settings_backupCategory": "バックアップ", "settings_backup": "バックアップ", "settings_title": "設定", - "settings_cat_subscription": "サブスクリプション", + "settings_cat_subscription": "定額利用", "settings_cat_drive": "CryptDrive", "settings_cat_account": "アカウント", "settings_save": "保存", @@ -125,7 +125,7 @@ "login_invalUser": "ユーザー名を入力してください", "register_importRecent": "匿名セッションのドキュメントをインポート", "importButton": "インポート", - "main_catch_phrase": "コラボレーションスイート
暗号化されかつオープンソース", + "main_catch_phrase": "コラボレーションスイート
端末間暗号化とオープンソース", "tos_3rdparties": "私たちは、法令に基づく場合を除き、個人情報を第三者に提供しません。", "tos_logs": "あなたのブラウザからサーバーに送信されたメタデータは、サービスを維持するために記録される場合があります。", "tos_availability": "私たちはこのサービスがあなたの役に立つことを願っていますが、可用性や性能は保証できません。定期的にデータをエクスポートしてください。", @@ -150,7 +150,7 @@ "logoutButton": "ログアウト", "login_login": "ログイン", "autostore_hide": "保存しない", - "autostore_store": "保存する", + "autostore_store": "保存", "autostore_notstored": "この{0}はあなたのCryptDriveに保存されていません。今すぐ保存しますか?", "user_displayName": "表示名", "exportButton": "エクスポート", @@ -166,13 +166,13 @@ "profile_upload": " 新しいアバターをアップロード", "teams_table_generic_edit": "編集: フォルダとパッドの作成、変更、削除が可能。", "teams_table_generic_view": "表示: フォルダとパッドへのアクセス(閲覧のみ)。", - "teams_table_generic_own": "チームの管理: チーム名とチームのアバターの変更、オーナーの追加または削除、チームのサブスクリプションの変更、チームの削除が可能。", + "teams_table_generic_own": "チームの管理: チーム名とチームのアバターの変更、オーナーの追加または削除、チームの定額利用に関する変更、チームの削除が可能。", "teams_table_owners": "チームの管理", "teams_table_generic_admin": "メンバーの管理: メンバーの招待および取り消し、メンバーに管理者までの権限の付与が可能。", "teams_table_admins": "メンバーの管理", "teams_table_generic": "権限一覧", "teams_table": "権限", - "contacts_fetchHistory": "古い履歴を取得する", + "contacts_fetchHistory": "古い履歴を取得", "contacts_warning": "ここに入力した全てのメッセージは永続的であり、このパッドの現在および将来の全てのユーザーが確認できます。機密情報の入力には注意してください!", "contacts_typeHere": "ここにメッセージを入力...", "team_cat_drive": "ドライブ", @@ -228,14 +228,14 @@ "notifications_cat_friends": "連絡先リクエスト", "notifications_dismiss": "確認済みにする", "settings_autostoreMaybe": "手動 (確認しない)", - "settings_autostoreNo": "手動 (常に確認する)", + "settings_autostoreNo": "手動(常に確認)", "settings_autostoreHint": "自動 アクセスした全てのパッドをCryptDriveに保存します。
手動(常に確認) 保存していないパッドにアクセスした際、CryptDriveに保存するかどうかを確認します。
手動(確認しない) アクセス先のパッドはCryptDriveに自動で保存されません。保存オプションは表示されません。", "settings_userFeedback": "ユーザーフィードバックを有効にする", "settings_userFeedbackHint2": "あなたのパッドのコンテンツがサーバーと共有されることはありません。", "settings_userFeedbackHint1": "CryptPadは、ユーザーエクスペリエンスの向上のため、いくつかの非常に基本的なフィードバックを、サーバーに提供します。 ", "settings_userFeedbackTitle": "フィードバック", "settings_autostoreYes": "自動", - "settings_importConfirm": "このブラウザで最近使用したパッドを、あなたのユーザーアカウントのCryptDriveにインポートしますか?", + "settings_importConfirm": "このブラウザで最近利用したパッドを、あなたのユーザーアカウントのCryptDriveにインポートしますか?", "settings_importDone": "インポートが完了しました", "settings_import": "インポート", "settings_importTitle": "このブラウザでの最近のパッドをあなたのCryptDriveにインポートします", @@ -246,7 +246,7 @@ "fc_delete": "ごみ箱へ移動", "fc_remove": "削除", "fc_restore": "復元", - "fc_delete_owned": "完全削除", + "fc_delete_owned": "破棄", "creation_create": "作成", "creation_password": "パスワード\n", "creation_expireMonths": "か月", @@ -266,7 +266,7 @@ "features_f_cryptdrive1": "CryptDriveの全機能", "features_f_anon_note": "追加機能あり", "features_f_anon": "匿名ユーザーの全機能", - "features_f_storage0_note": "ドキュメントは{0}日以上使用されないと削除されます", + "features_f_storage0_note": "ドキュメントは{0}日以上利用されないと削除されます", "features_f_storage0": "一時的な保存", "features_f_cryptdrive0_note": "アクセスしたパッドをブラウザに保存して、後で開くことができます", "features_f_cryptdrive0": "CryptDriveへの限定的なアクセス", @@ -322,7 +322,7 @@ "properties_passwordSuccessFile": "パスワードは正常に変更されました。", "drive_sfPasswordError": "誤ったパスワードです", "team_title": "チーム: {0}", - "password_error": "ドキュメントが存在しません!
このエラーは、誤ったパスワードが入力された場合、またはドキュメントがサーバーから完全削除された場合に発生します。", + "password_error": "ドキュメントが存在しません!
このエラーは、誤ったパスワードが入力された場合、またはドキュメントがサーバーから破棄された場合に発生します。", "password_error_seed": "パッドが存在しません!
このエラーは「パスワードが追加・変更された」場合、または「パッドがサーバーから削除された」場合に発生します。", "password_submit": "送信", "password_placeholder": "パスワードを入力...", @@ -332,7 +332,7 @@ "properties_addPassword": "パスワードを設定", "history_close": "閉じる", "history_restore": "復元", - "fm_emptyTrashOwned": "ごみ箱に、あなたが所有しているドキュメントが入っています。あなたのドライブからのみ削除するか、全てのユーザーから完全削除するかを選択できます。", + "fm_emptyTrashOwned": "ごみ箱に、あなたの所有するドキュメントが入っています。あなたのドライブからのみ削除するか、全てのユーザーから破棄するかを選択できます。", "access_destroyPad": "このドキュメントまたはフォルダを完全に削除する", "accessButton": "アクセス", "access_allow": "リスト", @@ -417,7 +417,7 @@ "fm_noname": "無題のドキュメント", "fm_openParent": "フォルダに表示", "fm_newButtonTitle": "新しいドキュメントやフォルダを作成したり、ファイルを現在のフォルダにインポートしたりできます。", - "contacts_info4": "チャットの参加者のどちらも履歴を削除できます", + "contacts_info4": "チャットの参加者は誰でも履歴を消去できます", "contacts_info2": "連絡先のアイコンをクリックしてチャットを開始", "contacts_confirmRemove": "{0}をあなたの連絡先から削除してよろしいですか?", "profile_error": "プロフィールの作成時にエラーが発生しました: {0}", @@ -475,7 +475,7 @@ "poll_create_option": "新しいオプションを追加", "poll_create_user": "新しいユーザーを追加", "pad_mediatagImport": "あなたのCryptDriveに保存", - "admin_listMyInstanceLabel": "このインスタンスをリストに表示する", + "admin_listMyInstanceLabel": "このインスタンスをリストに表示", "admin_checkupTitle": "インスタンスの設定を検証", "cba_disable": "消去して無効にする", "upload_pending": "保留中", @@ -595,7 +595,7 @@ "toolbar_file": "ファイル", "drive_treeButton": "ファイル", "toolbar_insert": "挿入", - "fm_sort": "並び替え", + "fm_sort": "並び替える", "comments_comment": "コメント", "comments_resolve": "解決", "comments_reply": "返信", @@ -765,25 +765,25 @@ "errorState": "重大なエラー: {0}", "realtime_unrecoverableError": "回復不能なエラーが発生しました。OKをクリックして再読み込みを行ってください。", "disabledApp": "このアプリケーションは無効になっています。詳細については、このCryptPadの管理者にお問い合わせください。", - "deletedFromServer": "パッドは完全削除されました", + "deletedFromServer": "ドキュメントが破棄されました", "newVersionError": "新しいバージョンのCryptPadがあります。
リロードすると新しいバージョンを読み込みます。Escキーを押すとオフラインモードでコンテンツにアクセスします。", "errorRedirectToHome": "Escキーを押すとCryptDriveにリダイレクトします。", "errorCopy": " Escキーを押すと、閲覧モードで引き続きコンテンツにアクセスできます。", "invalidHashError": "要求したドキュメントのURLが無効です。", "chainpadError": "コンテンツを更新する際に重大なエラーが発生しました。コンテンツが失われないよう、閲覧モードで表示されています。
このパッドを表示し続けるにはEscキーを押し、再度編集を試みるにはリロードをしてください。", - "inactiveError": "このパッドは使用されていなかったため削除されました。Escキーを押して新しいパッドを作成します。", - "deletedError": "このドキュメントは削除されたため、使用できなくなりました。", - "expiredError": "このパッドは使用期限が過ぎてしまったため、使用できなくなりました。", + "inactiveError": "このパッドは利用されていなかったため削除されました。Escキーを押すと新しいパッドを作成します。", + "deletedError": "このドキュメントは削除されたため、利用できなくなりました。", + "expiredError": "このパッドは利用期限を過ぎてしまったため、利用できなくなりました。", "anonymousStoreDisabled": "このCryptPadのインスタンスの管理者は、匿名ユーザーによる保存を無効に設定しています。CryptDriveを使用するにはログインする必要があります。", - "padNotPinnedVariable": "このパッドは{4}日使用しないと期限切れになります。{0}ログイン{1}または{2}登録{3}し保存してください。", - "padNotPinned": "このパッドは3ヶ月間使用しないと有効期限が切れます。{0}ログイン{1}するか{2}登録{3}して保存してください。", + "padNotPinnedVariable": "このパッドは{4}日間利用しないと有効期限が切れます。{0}ログイン{1}するか{2}登録{3}して保存してください。", + "padNotPinned": "このパッドは3か月間利用しないと有効期限が切れます。{0}ログイン{1}するか{2}登録{3}して保存してください。", "onLogout": "ログアウトしました。{0}ここをクリック{1}するか
Escapeキーを押すと、閲覧モードでパッドにアクセスできます。", "typeError": "このパッドは選択したアプリケーションと互換性がありません", "form_type_page": "ページ分割", "form_description_default": "ここにテキストを入力", "team_pcsSelectHelp": "所有するパッドをチームのドライブに作成すると、そのパッドのオーナー権はチームに与えられます。", "sharedFolders_create_owned": "所有するフォルダ", - "creation_owned1": "所有している項目は、オーナーの望むときにいつでも完全削除できます。完全削除すると、他のユーザーのCryptDriveからも削除されます。", + "creation_owned1": "所有している項目は、オーナーの望むときにいつでも破棄できます。破棄すると、他のユーザーのCryptDriveからも削除されます。", "creation_owned": "パッドを所有", "uploadFolder_modal_owner": "所有するファイル", "upload_modal_owner": "所有するファイル", @@ -824,7 +824,7 @@ "pad_goToAnchor": "アンカーに移動", "oo_cantMigrate": "この表はアップロードの最大のサイズを超えているため、移行することができません。", "footer_roadmap": "ロードマップ", - "settings_deleteSubscription": "サブスクリプションを管理", + "settings_deleteSubscription": "定額利用を管理", "broadcast_translations": "翻訳", "admin_broadcastCancel": "メッセージを削除", "admin_broadcastButton": "送信", @@ -1252,7 +1252,7 @@ "owner_removeMeConfirm": "オーナー権を放棄しようとしています。これは取り消せません。よろしいですか?", "requestEdit_confirm": "{1}がパッド「{0}」の編集権を要求しました。編集権を与えますか?", "admin_supportInitHelp": "サーバーはサポートメールボックスを使用するように設定されていません。サポートメールボックスを有効にし、ユーザーからメッセージを受け取るためには、サーバーの管理者に連絡し、「./scripts/generate-admin-keys.js」のスクリプトを実行してもらい、生成された公開鍵を「config.js」に保存して、秘密鍵をあなたに送信してもらうよう依頼する必要があります。", - "feedback_privacy": "私たちはプライバシーを配慮すると同時に、CryptPadを使いやすくしたいと望んでいます。このファイルは、実行されたアクションを特定するパラメーターと共に要求され、ユーザーにとって重要なUI機能を特定するために使用されます。", + "feedback_privacy": "私たちはプライバシーに配慮すると同時に、CryptPadを使いやすくしたいと望んでいます。このファイルは、実行されたアクションを特定するパラメーターと共に要求され、ユーザーにとって重要なUI機能を特定するために使用されます。", "register_warning_note": "暗号化を行うCryptPadの性質上、サービス管理者は、ユーザー名とパスワードを忘れた場合にデータを回復することができません。ユーザー名とパスワードを安全な場所に保管してください。", "history_restoreDriveTitle": "選択したバージョンのCryptDriveを復元", "errorPopupBlocked": "新しいタブを開く許可が必要です。お使いのブラウザのアドレスバーから、ポップアップウィンドウを許可してください。これらのウィンドウが広告の表示に使用されることはありません。", @@ -1308,8 +1308,8 @@ "share_linkPasswordAlert": "この項目はパスワードで保護されています。リンクを受け取った相手はパスワードを入力する必要があります。", "register_notes_title": "重要な注意事項", "teams_table_specificHint": "以前のバージョンの共有フォルダでは、閲覧者は既存のパッドを変更することができます。 これらのフォルダで作成またはコピーしたパッドには、標準の権限が与えられます。", - "broadcast_maintenance": "{0}から{1}の間でメンテナンスを予定しています。その間CryptPadは使用できません。", - "admin_archiveHint": "ドキュメントを完全削除することなく、利用できないよう設定できます。「アーカイブ」フォルダに移動し、数日後に削除します(期間については設定ファイルより設定できます)。", + "broadcast_maintenance": "{0}から{1}の間でメンテナンスを予定しています。その間CryptPadは利用できません。", + "admin_archiveHint": "ドキュメントを破棄することなく、利用できないよう設定できます。「アーカイブ」フォルダに移動し、数日後に削除します(期間については設定ファイルより設定できます)。", "admin_unarchiveHint": "アーカイブされたドキュメントを復元できます", "admin_registrationTitle": "登録を締め切る", "admin_defaultlimitHint": "ユーザー定義のルールが適用されていない際の最大のストレージ容量(ユーザーとチームについて)を設定できます", diff --git a/www/common/translations/messages.lt.json b/www/common/translations/messages.lt.json index bd3a3a86b..9d252e196 100644 --- a/www/common/translations/messages.lt.json +++ b/www/common/translations/messages.lt.json @@ -182,5 +182,27 @@ "tags_add": "Atnaujinkite pažymėtų padų žymas", "tags_title": "Žymos (tik jums)", "filePicker_filter": "Filtruokite failus pagal pavadinimą", - "filePicker_description": "Pasirinkite failą iš „CryptDrive“, kad jį įdėtumėte arba įkeltumėte naują" + "filePicker_description": "Pasirinkite failą iš „CryptDrive“, kad jį įdėtumėte arba įkeltumėte naują", + "oo_cantUpload": "Įkelti negalima, kol dalyvauja kiti vartotojai.", + "oo_reconnect": "Serverio ryšys atkurtas. Spustelėkite Gerai, jei norite iš naujo įkelti ir tęsti leidimą.", + "poll_comment_disabled": "Paskelbkite šią apklausą naudodami mygtuką ✓, kad įgalintumėte komentarus.", + "poll_comment_placeholder": "Jūsų komentaras", + "poll_comment_remove": "Ištrinti šį komentarą", + "poll_comment_submit": "Siųsti", + "poll_comment_add": "Pridėti komentarą", + "poll_comment_list": "Komentarai", + "poll_total": "Bendras", + "poll_bookmarked_col": "Tai yra jūsų pažymėtas stulpelis. Jums visada bus atrakinta ir rodoma pradžioje.", + "poll_bookmark_col": "Pažymėkite šį stulpelį taip, kad jis visada būtų atrakintas ir rodomas pradžioje", + "poll_unlocked": "Atrakinta", + "poll_locked": "Užrakinta", + "poll_edit": "Redaguoti", + "poll_remove": "Pašalinti", + "poll_descriptionHint": "Apibūdinkite apklausą ir, kai baigsite, naudokite mygtuką ✓ (paskelbti).\nAprašymas gali būti parašytas naudojant žymėjimo sintaksę ir galite įdėti laikmenos elementus iš savo „CryptDrive“.\nVisi, turintys nuorodą, gali pakeisti aprašą, tačiau tai nerekomenduojama.", + "poll_removeUser": "Ar tikrai norite pašalinti šį vartotoją?", + "poll_removeOption": "Ar tikrai norite pašalinti šią parinktį?", + "poll_userPlaceholder": "Vardas", + "poll_optionPlaceholder": "Pasirinkimai", + "poll_commit": "Pateikti", + "poll_create_option": "Pridėti naują parinktį" } diff --git a/www/common/translations/messages.zh.json b/www/common/translations/messages.zh.json index 49331f9a5..ca0b85c73 100644 --- a/www/common/translations/messages.zh.json +++ b/www/common/translations/messages.zh.json @@ -13,7 +13,8 @@ "todo": "待办事项", "teams": "团队", "sheet": "工作表", - "contacts": "联系我们" + "contacts": "联系我们", + "form": "从" }, "button_newpad": "富文件檔案", "button_newcode": "新代碼檔案", diff --git a/www/form/inner.js b/www/form/inner.js index 8db1f8e16..b3db8ce79 100644 --- a/www/form/inner.js +++ b/www/form/inner.js @@ -298,6 +298,7 @@ define([ del ]); $(del).click(function () { + var $block = $(el).closest('.cp-form-edit-block'); $(el).remove(); // We've just deleted an item/option so we should be under the MAX limit and // we can show the "add" button again @@ -306,6 +307,13 @@ define([ $add.show(); if (v.type === "time") { $(addMultiple).show(); } } + // decrement the max choices input when there are fewer options than the current maximum + if (maxInput) { + var inputs = $block.find('input').length; + var $maxInput = $(maxInput); + var currentMax = Number($maxInput.val()); + $maxInput.val(Math.min(inputs, currentMax)); + } }); return el; }; @@ -729,7 +737,7 @@ define([ var answer = answerObj.results; if (!answer || !answer.values) { return; } var values = answer.values || {}; - var res = Number(values[data]) || 0; // XXX inc function ? + var res = Number(values[data]) || 0; if (res === 1) { y++; } else if (res === 2) { m++; } }); @@ -776,7 +784,7 @@ define([ }; refreshBest(); - if (myLine && evOnChange) { // XXX + if (myLine && evOnChange) { var updateValues = function () { totalEls.forEach(function (cell) { var $c = $(cell); @@ -784,7 +792,7 @@ define([ if (!data) { return; } var y = totals[data].y + ((myTotals[data] || {}).y || 0); var m = totals[data].m + ((myTotals[data] || {}).m || 0); - $c.find('.cp-form-total-yes').text(y); // XXX inc function + $c.find('.cp-form-total-yes').text(y); $c.find('.cp-form-total-maybe').text('('+m+')'); }); }; @@ -986,7 +994,7 @@ define([ printResults: function (answers, uid) { var results = []; var empty = 0; - Object.keys(answers).forEach(function (author) { // XXX deduplicate these? + Object.keys(answers).forEach(function (author) { // TODO deduplicate these? var obj = answers[author]; var answer = obj.msg[uid]; if (!answer || !answer.trim()) { return empty++; } @@ -998,7 +1006,7 @@ define([ }, icon: h('i.cptools.cptools-form-text') }, - textarea: { // XXX + textarea: { defaultOpts: { maxLength: 1000 }, @@ -1052,7 +1060,7 @@ define([ printResults: function (answers, uid) { var results = []; var empty = 0; - Object.keys(answers).forEach(function (author) { // XXX deduplicate these + Object.keys(answers).forEach(function (author) { // TODO deduplicate these var obj = answers[author]; var answer = obj.msg[uid]; if (!answer || !answer.trim()) { return empty++; } @@ -1126,8 +1134,7 @@ define([ var obj = answers[author]; var answer = obj.msg[uid]; if (!answer || !answer.trim()) { return empty++; } - count[answer] = count[answer] || 0; // XXX inc function - count[answer]++; + Util.inc(count, answer); }); Object.keys(count).forEach(function (value) { results.push(h('div.cp-form-results-type-radio-data', [ @@ -1229,8 +1236,7 @@ define([ var c = count[q_uid] = count[q_uid] || {}; var res = answer[q_uid]; if (!res || !res.trim()) { return; } - c[res] = c[res] || 0; // XXX inc function - c[res]++; + Util.inc(c, res); }); }); Object.keys(count).forEach(function (q_uid) { @@ -1340,8 +1346,7 @@ define([ var answer = obj.msg[uid]; if (!Array.isArray(answer) || !answer.length) { return empty++; } answer.forEach(function (val) { - count[val] = count[val] || 0; // XXX inc function - count[val]++; + Util.inc(count, val); }); }); Object.keys(count).forEach(function (value) { @@ -1455,9 +1460,8 @@ define([ var c = count[q_uid] = count[q_uid] || {}; var res = answer[q_uid]; if (!Array.isArray(res) || !res.length) { return; } - res.forEach(function (v) { // XXX increment function? - c[v] = c[v] || 0; - c[v]++; + res.forEach(function (v) { + Util.inc(c, v); }); }); }); @@ -1595,7 +1599,7 @@ define([ if (!Array.isArray(answer) || !answer.length) { return empty++; } answer.forEach(function (el, i) { var score = l - i; - count[el] = (count[el] || 0) + score; // XXX inc function? + Util.inc(count, el, score); }); }); var sorted = Object.keys(count).sort(function (a, b) { @@ -1974,7 +1978,7 @@ define([ value: user.name || '', placeholder: Messages.form_anonName }) - ]) + ]); $anonName = $(anonName).hide(); $anonBox.on('change', function () { if (Util.isChecked($anonBox)) { $anonName.hide(); } @@ -2566,10 +2570,11 @@ define([ var responseMsg = h('div.cp-form-response-msg-container'); var $responseMsg = $(responseMsg); var refreshResponse = function () { + if (true) { return; } // XXX 4.10.0 $responseMsg.empty(); - Messages.form_updateMsg = "Update response message"; // XXX - Messages.form_addMsg = "Add response message"; - Messages.form_responseMsg = "Add a message that will be displayed in the response page."; + Messages.form_updateMsg = "Update response message"; // XXX 4.10.0 + Messages.form_addMsg = "Add response message"; // XXX 4.10.0 + Messages.form_responseMsg = "Add a message that will be displayed in the response page."; // XXX 4.10.0 var text = content.answers.msg ? Messages.form_updateMsg : Messages.form_addMsg; var btn = h('button.btn.btn-secondary', text); $(btn).click(function () { @@ -2598,7 +2603,7 @@ define([ name: Messages.settings_save, onClick: function () { var v = editor.getValue(); - content.answers.msg = v.trim(0, 2000); // XXX max length? + content.answers.msg = v.trim(0, 2000); // XXX 4.10.0 max length? framework.localChange(); framework._.cpNfInner.chainpad.onSettle(function () { UI.log(Messages.saved); @@ -2624,9 +2629,9 @@ define([ } UI.openCustomModal(APP.responseModal); }); - $responseMsg.append(btn); + // $responseMsg.append(btn); // XXX 4.10.0 }; - refreshResponse(); + //refreshResponse(); // Allow anonymous answers var privacyContainer = h('div.cp-form-privacy-container'); @@ -2723,7 +2728,7 @@ define([ evOnChange.reg(refreshPublic); evOnChange.reg(refreshPrivacy); evOnChange.reg(refreshEndDate); - evOnChange.reg(refreshResponse); + //evOnChange.reg(refreshResponse); return [ endDateContainer,