mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-14 11:05:41 +05:00
Merge branch 'staging' into update-icons
# Conflicts: # customize.dist/src/less2/include/toolbar.less # www/calendar/app-calendar.less # www/calendar/inner.js
This commit is contained in:
commit
71e5b53950
5
.github/ISSUE_TEMPLATE/bug_resolution.yml
vendored
5
.github/ISSUE_TEMPLATE/bug_resolution.yml
vendored
@ -89,10 +89,9 @@ body:
|
||||
label: Version
|
||||
description: What version of CryptPad are you running?
|
||||
options:
|
||||
- 2025.6.0
|
||||
- 2025.3.1
|
||||
- 2025.3.0
|
||||
- 2024.12.0
|
||||
- 2024.9.1
|
||||
- 2024.9.0
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
39
.github/workflows/test-trigger.yml
vendored
Normal file
39
.github/workflows/test-trigger.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# SPDX-FileCopyrightText: 2025 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
name: Trigger E2E tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ staging, 2025.9-rc, 2025.9-test ]
|
||||
|
||||
jobs:
|
||||
trigger-tests:
|
||||
if: github.ref_name == 'staging'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger E2E test run (local)
|
||||
run: |
|
||||
branch="${GITHUB_REF_NAME}"
|
||||
|
||||
if [ "$branch" = "staging" ]; then
|
||||
event_type="trigger-e2e-tests-staging"
|
||||
elif [ "$branch" = "2025.9-rc" ]; then
|
||||
event_type="trigger-e2e-tests-rc"
|
||||
elif [ "$branch" = "2025.9-test" ]; then
|
||||
event_type="trigger-e2e-tests-test"
|
||||
fi
|
||||
|
||||
repo_owner="cryptpad"
|
||||
repo_name="e2e-test-suite"
|
||||
|
||||
curl -L \
|
||||
-X POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.TEST_PAT }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/cryptpad/e2e-test-suite/dispatches \
|
||||
-d "{\"event_type\": \"$event_type\", \"client_payload\": {\"service\": \"$service\", \"version\": \"$version\", \"unit\": false, \"integration\": true}}"
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@
|
||||
|
||||
.cp-markdown-toolbar {
|
||||
min-height: @toolbar_line-height;
|
||||
padding: 0.1rem 0;
|
||||
padding: 0.15rem 0.20rem;
|
||||
height: auto;
|
||||
flex-wrap: wrap;
|
||||
background-color: @cp_toolbar-bg;
|
||||
@ -73,6 +73,7 @@
|
||||
border-radius: @variables_radius;
|
||||
color: @toolbar-color;
|
||||
.toolbar_button;
|
||||
padding: 3px 9px;
|
||||
&:hover {
|
||||
background-color: contrast(@cp_toolbar-bg, darken(@cp_toolbar-bg, 5%), lighten(@cp_toolbar-bg, 5%));
|
||||
}
|
||||
|
||||
@ -255,6 +255,30 @@ server {
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
}
|
||||
|
||||
location ~ ^/upload-blob {
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' "${allowed_origins}";
|
||||
add_header 'Access-Control-Allow-Credentials' true;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Authorization';
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Content-Type' 'application/octet-stream; charset=utf-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
# These settings prevent both NGINX and the API server
|
||||
# from setting the same headers and creating duplicates
|
||||
proxy_hide_header Cross-Origin-Resource-Policy;
|
||||
add_header Cross-Origin-Resource-Policy cross-origin;
|
||||
proxy_hide_header Cross-Origin-Embedder-Policy;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
}
|
||||
|
||||
# Requests for blobs and blocks are now proxied to the API server
|
||||
# This simplifies NGINX path configuration in the event they are being hosted in a non-standard location
|
||||
# or with odd unexpected permissions. Serving blobs in this manner also means that it will be possible to
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
!/bin/sh
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
# PROVIDE: cryptpad
|
||||
# REQUIRE: DAEMON nginx
|
||||
|
||||
@ -98,7 +98,7 @@ module.exports.create = function (config) {
|
||||
|
||||
protocol: new URL(httpUnsafeOrigin).protocol,
|
||||
|
||||
fileHost: config.fileHost || undefined,
|
||||
fileHost: config.fileHost? new URL(config.fileHost).origin : undefined,
|
||||
NO_SANDBOX: NO_SANDBOX,
|
||||
httpSafePort: httpSafePort,
|
||||
websocketPort: config.websocketPort,
|
||||
|
||||
@ -107,6 +107,10 @@ HK.authenticateNetfluxSession = function (Env, netfluxId, unsafeKey) {
|
||||
var user = Env.netfluxUsers[netfluxId] = Env.netfluxUsers[netfluxId] || {};
|
||||
user[unsafeKey] = +new Date();
|
||||
};
|
||||
HK.unauthenticateNetfluxSession = function (Env, netfluxId, unsafeKey) {
|
||||
var user = Env.netfluxUsers[netfluxId] = Env.netfluxUsers[netfluxId] || {};
|
||||
delete user[unsafeKey];
|
||||
};
|
||||
|
||||
HK.closeNetfluxSession = function (Env, netfluxId) {
|
||||
delete Env.netfluxUsers[netfluxId];
|
||||
@ -804,7 +808,7 @@ const handleGetHistoryRange = function (Env, Server, seq, userId, parsed) {
|
||||
if (hash === untilHash || untilHash === 'NONE') { found = true; }
|
||||
let then = hash === oldestKnownHash ? abort : readMore;
|
||||
if (found) {
|
||||
Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId,
|
||||
return void Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId,
|
||||
JSON.stringify(['HISTORY_RANGE', txid, parsed])], then);
|
||||
}
|
||||
return void readMore();
|
||||
|
||||
@ -72,6 +72,7 @@ const AUTHENTICATED_USER_SCOPED = {
|
||||
REMOVE_PINS: Pinning.removePins,
|
||||
TRIM_PINS: Pinning.trimPins,
|
||||
COOKIE: Core.haveACookie,
|
||||
DESTROY: () => {}
|
||||
};
|
||||
|
||||
var isAuthenticatedCall = function (call) {
|
||||
@ -190,6 +191,11 @@ var rpc = function (Env, Server, userId, data, respond) {
|
||||
if (command === 'COOKIE' && !hadSession && Env.logIP) {
|
||||
Env.Log.info('NEW_RPC_SESSION', {userId: userId, publicKey: publicKey});
|
||||
}
|
||||
if (command === "DESTROY") {
|
||||
HK.unauthenticateNetfluxSession(Env, userId, publicKey);
|
||||
return; // No need to respond, user will close the session
|
||||
}
|
||||
|
||||
HK.authenticateNetfluxSession(Env, userId, publicKey);
|
||||
return void handleAuthenticatedMessage(Env, publicKey, msg, respond, Server);
|
||||
});
|
||||
|
||||
@ -264,6 +264,8 @@ var factory = function (Util, Nacl) {
|
||||
clearTimeout(to);
|
||||
});
|
||||
|
||||
ctx.send('DESTROY', "", function () {});
|
||||
|
||||
// remove the ctx from the network's stack
|
||||
var idx = networkContext.authenticated.indexOf(ctx);
|
||||
if (idx === -1) { return; }
|
||||
|
||||
@ -25,6 +25,7 @@ const factory = (Sortify, UserObject, ProxyManager,
|
||||
const Saferphore = Util.Saferphore;
|
||||
var onReadyEvt = Util.mkEvent(true);
|
||||
var onCacheReadyEvt = Util.mkEvent(true);
|
||||
var onDriveReadyEvt = Util.mkEvent(true);
|
||||
var onPadRejectedEvt = Util.mkEvent(true);
|
||||
|
||||
const setCustomize = data => {
|
||||
@ -1608,7 +1609,7 @@ const factory = (Sortify, UserObject, ProxyManager,
|
||||
if (!Array.isArray(allowed)) { return void cb('ERESTRICTED'); }
|
||||
|
||||
onPadRejectedEvt.fire();
|
||||
onReadyEvt.reg(() => {
|
||||
onDriveReadyEvt.reg(() => {
|
||||
// There is an allow list: check if we can authenticate
|
||||
if (!store.loggedIn || !store.proxy.edPublic) { return void cb('ERESTRICTED'); }
|
||||
|
||||
@ -2570,6 +2571,7 @@ const factory = (Sortify, UserObject, ProxyManager,
|
||||
cacheCb(store.cacheReturned || store.returned);
|
||||
});
|
||||
onDriveReady(() => {
|
||||
onDriveReadyEvt.fire();
|
||||
cb(store.returned);
|
||||
});
|
||||
|
||||
|
||||
@ -24,7 +24,16 @@ const factory = (Crypto) => {
|
||||
msg: data.msg,
|
||||
uid: data.uid,
|
||||
};
|
||||
chan.sendMsg(JSON.stringify(obj), cb);
|
||||
if (obj.msg === 'ISAVE') {
|
||||
ctx.pending[data.uid] = true;
|
||||
}
|
||||
chan.sendMsg(JSON.stringify(obj), obj => {
|
||||
if (!ctx.pending[data.uid]) {
|
||||
return void setTimeout(cb, 1000);
|
||||
}
|
||||
delete ctx.pending[data.uid];
|
||||
cb(obj);
|
||||
});
|
||||
ctx.emit('MESSAGE', obj, chan.clients.filter(function (cl) {
|
||||
return cl !== client;
|
||||
}));
|
||||
@ -90,6 +99,9 @@ const factory = (Crypto) => {
|
||||
var parsed;
|
||||
try {
|
||||
parsed = JSON.parse(msg);
|
||||
if (parsed.msg === "ISAVE") {
|
||||
delete ctx.pending[parsed.uid];
|
||||
}
|
||||
ctx.emit('MESSAGE', parsed, chan.clients);
|
||||
} catch (e) { console.error(e); }
|
||||
});
|
||||
@ -176,6 +188,7 @@ const factory = (Crypto) => {
|
||||
store: cfg.store,
|
||||
emit: emit,
|
||||
channels: {},
|
||||
pending: {}, // prevent ISAVE race condition
|
||||
clients: {}
|
||||
};
|
||||
|
||||
|
||||
@ -107,6 +107,7 @@ const factory = (Util, Hash, Constants, Realtime, ProxyManager,
|
||||
try { team.roster.stop(); } catch (e) {}
|
||||
team.proxy = {};
|
||||
team.stopped = true;
|
||||
team?.rpc?.destroy();
|
||||
delete ctx.teams[teamId];
|
||||
delete ctx.cache[teamId];
|
||||
delete ctx.store.proxy.teams[teamId];
|
||||
|
||||
@ -78,6 +78,7 @@ let start = (cfg: StoreConfig):void => {
|
||||
Store,
|
||||
Account,
|
||||
Mailbox,
|
||||
Messenger,
|
||||
Badge
|
||||
].forEach(dep => {
|
||||
if (typeof(dep.setCustomize) === "function") {
|
||||
|
||||
@ -172,6 +172,10 @@
|
||||
text-align:center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tui-full-calendar-calendar-dot {
|
||||
margin-right: 10px;
|
||||
top: 0;
|
||||
}
|
||||
.tui-full-calendar-popup-detail-item {
|
||||
display: flex;
|
||||
margin-bottom: 0.3rem;
|
||||
@ -195,7 +199,6 @@
|
||||
}
|
||||
}
|
||||
a {
|
||||
margin:0.1rem;
|
||||
border-radius: @variables_radius;
|
||||
color: @cryptpad_color_link;
|
||||
text-decoration: underline;
|
||||
@ -314,6 +317,9 @@
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
* {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
.CodeMirror-placeholder {
|
||||
color: @cp_forms-placeholder;
|
||||
|
||||
@ -2387,6 +2387,23 @@ APP.recurrenceRule = {
|
||||
});
|
||||
}
|
||||
|
||||
var privateData = metadataMgr.getPrivateData();
|
||||
$el.find('.event-description').click(e => {
|
||||
if (!e.target) { return; }
|
||||
var $t = $(e.target);
|
||||
if (!$t.is('a') && !$t.parents('a').length) { return; }
|
||||
e.preventDefault();
|
||||
var $a = $t.is('a') ? $t : $t.parents('a').first();
|
||||
var href = $a.attr('href');
|
||||
if (/^#/.test(href)) { return; }
|
||||
if (/^\/[^\/]/.test(href)) {
|
||||
href = privateData.origin + href;
|
||||
return void common.openURL(href);
|
||||
}
|
||||
common.openUnsafeURL(href);
|
||||
});
|
||||
console.error($el.find('.event-description'), $el);
|
||||
|
||||
var $section = $el.find('.tui-full-calendar-section-button');
|
||||
var ev = APP.editModalData;
|
||||
var data = ev.schedule || {};
|
||||
|
||||
@ -1651,6 +1651,27 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
// confirm that POST requests to the `/upload-blob` endpoint
|
||||
// return something other than a 404, which would probably indicate
|
||||
// a reverse proxy misconfiguration
|
||||
assert(function (cb, msg) {
|
||||
msg.appendChild(h('span', [
|
||||
`The server returned a 404 error when attempting to reach the `,
|
||||
h('code', `/upload-blob`),
|
||||
` endpoint. This can be caused by an incorrectly configured reverse proxy.`,
|
||||
]));
|
||||
|
||||
fetch('/upload-blob', {
|
||||
method: 'POST',
|
||||
}).then(res => {
|
||||
console.log({ upload_fetch_response: res });
|
||||
cb(res.status !== 404);
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
cb(false);
|
||||
});
|
||||
});
|
||||
|
||||
var row = function (cells) {
|
||||
return h('tr', cells.map(function (cell) {
|
||||
return h('td', cell);
|
||||
|
||||
@ -80,7 +80,9 @@ define([
|
||||
var keys = [];
|
||||
nThen(function (waitFor) {
|
||||
// Not logged in? check for temp RPC keys
|
||||
if (!LocalStore.isLoggedIn() && Env?.returned?.tempKeys) {
|
||||
const anon = !LocalStore.isLoggedIn()
|
||||
|| common.neverDrive;
|
||||
if (anon && Env?.returned?.tempKeys) {
|
||||
keys.push(Env.returned.tempKeys);
|
||||
return;
|
||||
}
|
||||
@ -2672,6 +2674,7 @@ define([
|
||||
Messages,
|
||||
AppConfig
|
||||
};
|
||||
common.neverDrive = rdyCfg.neverDrive;
|
||||
common.userHash = userHash || LocalStore.getUserHash();
|
||||
|
||||
// FIXME Backward compatibility
|
||||
|
||||
@ -2163,7 +2163,7 @@ define([
|
||||
url: url,
|
||||
permissions: {
|
||||
download: dc?.permissions?.download || false,
|
||||
print: dc?.permissions?.print || true,
|
||||
print: dc?.permissions?.print !== false,
|
||||
protect: file.type === 'xlsx',
|
||||
}
|
||||
},
|
||||
|
||||
@ -670,6 +670,10 @@ define([
|
||||
|
||||
UI.removeLoadingScreen(emitResize);
|
||||
|
||||
if (integrationChannel) {
|
||||
integrationChannel.event('EV_INTEGRATION_READY');
|
||||
}
|
||||
|
||||
if (AppConfig.textAnalyzer && textContentGetter) {
|
||||
AppConfig.textAnalyzer(textContentGetter, privateDat.channel);
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ define([
|
||||
if (state.me) { return; } // I have the lock: abort
|
||||
if (state.other && state.other !== data.uid) { return; } // someone else has the lock
|
||||
// If state.other === data.uid ==> save failed and someone else tries again
|
||||
if (!state.changed) { return; }
|
||||
if (!state.changed && state.other !== data.uid) { return; }
|
||||
// If !state.other: nobody has the lock, give them
|
||||
state.other = data.uid;
|
||||
state.lastTmp = +new Date();
|
||||
@ -103,6 +103,7 @@ define([
|
||||
setStateChanged(false);
|
||||
saveTo = setTimeout(function () {
|
||||
// They weren't able to save in time, try ourselves
|
||||
setStateChanged(true);
|
||||
var id = state.other;
|
||||
state.other = false;
|
||||
save(id);
|
||||
@ -151,7 +152,7 @@ define([
|
||||
// is already saving
|
||||
requestSave = function (id, cb) {
|
||||
if (state.other || state.me) { return void cb(false); } // save in progress
|
||||
debug('Integration send ISAVE');
|
||||
debug('Integration send ISAVE', id);
|
||||
alreadySaved = false; // someone may have saved while we were waiting for our callback
|
||||
execCommand('SEND', {
|
||||
msg: 'ISAVE',
|
||||
|
||||
@ -609,7 +609,7 @@
|
||||
"friendRequest_later": "Tentukan nanti",
|
||||
"friendRequest_accept": "Terima (Enter)",
|
||||
"profile_addDescription": "Tambahkan deskripsi",
|
||||
"profile_addLink": "Tambahkan tautan ke situs web Anda",
|
||||
"profile_addLink": "Tautan ke situs web Anda",
|
||||
"notification_padShared": "{0} telah membagikan dokumen dengan Anda: <b>{1}</b>",
|
||||
"notification_folderShared": "{0} telah membagikan folder dengan Anda: <b>{1}</b>",
|
||||
"share_filterFriend": "Cari berdasarkan nama",
|
||||
@ -622,7 +622,7 @@
|
||||
"footer_donate": "Berdonasi",
|
||||
"drive_active7Days": "7 hari terakhir",
|
||||
"drive_active28Days": "4 minggu terakhir",
|
||||
"profile_editDescription": "Sunting deskripsi Anda",
|
||||
"profile_editDescription": "Deskripsi profil",
|
||||
"notification_fileShared": "{0} telah membagikan berkas dengan Anda: <b>{1}</b>",
|
||||
"admin_supportAddError": "Kunci privat tidak absah",
|
||||
"password_info": "Dokumen yang Anda buka sudah tidak ada atau dilindungi dengan kata sandi baru. Masukkan kata sandi yang benar untuk mengakses kontennya.",
|
||||
@ -1091,7 +1091,7 @@
|
||||
"mediatag_notReady": "Silakan selesaikan unduhan",
|
||||
"addOptionalPassword": "Tambahkan kata sandi (opsional)",
|
||||
"broadcast_defaultLanguage": "Gunakan bahasa ini sebagai cadangan",
|
||||
"calendar_errorNoCalendar": "Tidak ada kalender dapat disunting yang dipilih",
|
||||
"calendar_errorNoCalendar": "Tidak ada kalender yang tersedia",
|
||||
"calendar_import": "Tambahkan ke kalender saya",
|
||||
"calendar_dateTimeRange": "{0} {1} - {2}",
|
||||
"admin_supportPrivTitle": "Kunci pribadi kotak surat bantuan",
|
||||
@ -1174,7 +1174,7 @@
|
||||
"calendar_more": "{0} lagi",
|
||||
"form_invalidQuestion": "Pertanyaan {0}",
|
||||
"mdToolbar_embed": "Sematkan berkas",
|
||||
"fm_link_invalid": "URL tidak valid",
|
||||
"fm_link_invalid": "Silakan sediakan URL yang valid",
|
||||
"calendar_str_monthly": "{0} bulan",
|
||||
"comments_reply": "Balas",
|
||||
"comments_resolve": "Selesaikan",
|
||||
@ -1780,5 +1780,66 @@
|
||||
"admin_onboardingNamePlaceholder": "Judul server",
|
||||
"admin_onboardingDescPlaceholder": "Teks deskripsi server",
|
||||
"admin_onboardingOptionsHint": "Silakan pilih opsi sesuai untuk server Anda.<br>Pengaturan ini dapat diubah lagi dalam panel admin.",
|
||||
"install_notes": "<ul class=\"cp-notes-list\"><li>Buat akun administrator Anda yang pertama di laman ini. Administrator mengelola pengaturan server termasuk kuota penyimpanan dan memiliki akses ke peralatan moderasi.</li><li>Kata sandi Anda adalah kunci rahasia yang mengenkripsi semua dokumen dan hak administrator Anda di server ini.<span class=\"red\">Jika Anda kehilangan kata sandi tersebut, kami tidak dapat memulihkan data Anda.</span></li><li>Jika Anda menggunakan komputer terbagi, <span class=\"red\">jangan lupa untuk keluar dari akun</span> setelah Anda selesai. Hanya menutup jendela peramban membuat akun Anda rentan.</li></ul>"
|
||||
"install_notes": "<ul class=\"cp-notes-list\"><li>Buat akun administrator Anda yang pertama di laman ini. Administrator mengelola pengaturan server termasuk kuota penyimpanan dan memiliki akses ke peralatan moderasi.</li><li>Kata sandi Anda adalah kunci rahasia yang mengenkripsi semua dokumen dan hak administrator Anda di server ini.<span class=\"red\">Jika Anda kehilangan kata sandi tersebut, kami tidak dapat memulihkan data Anda.</span></li><li>Jika Anda menggunakan komputer terbagi, <span class=\"red\">jangan lupa untuk keluar dari akun</span> setelah Anda selesai. Hanya menutup jendela peramban membuat akun Anda rentan.</li></ul>",
|
||||
"form_passwordWarning": "Diingat bahwa kata sandi Form hanya dapat diatur sekarang pada waktu pembuatan dan tidak dapat diubah nanti.",
|
||||
"admin_addKeyLabel": "Tambahkan admin menggunakan kunci publiknya",
|
||||
"admin_documentsDeletionTitle": "Arsipkan beberapa dokumen",
|
||||
"admin_addAdminsHint": "Tambahkan administrator dari kunci publiknya atau dari daftar kontak Anda",
|
||||
"admin_listConfirm": "Apakah Anda yakin ingin menghapus hak admin dari pengguna ini?",
|
||||
"skipLink": "Lewati ke konten utama",
|
||||
"toggleArrows": "Tombol panah untuk memindahkan item",
|
||||
"oo_couldNotConvertDocument": "Konversi dokumen gagal. Saat ini format Microsoft Office (.docx, .xlsx, .pptx) memberikan hasil terbaik untuk pengimporan dan pengeksporan.",
|
||||
"admin_documentsDeletionHint": "Arsipkan daftar dokumen menggunakan id-nya (satu id dokumen per baris)",
|
||||
"fm_restoreMultipleDialog": "Apakah Anda yakin ingin memulihkan {0} berkas dan/atau folder ke tempat sebelumnya?",
|
||||
"calendar_show": "Tampilkan kalender",
|
||||
"calendar_hide": "Sembunyikan kalender",
|
||||
"oo_unstableMigrationWarning": "Impor dan Ekspor beberapa format OpenDocument (.odt, .odp) saat ini tidak stabil. Kami menyarankan menggunakan format lain jika dimungkinkan. CryptPad akan mencoba konversi sebaik mungkin.",
|
||||
"admin_logoSize_error": "Ukuran logo terlalu besar",
|
||||
"error_limit": "Silakan masukkan angka yang valid",
|
||||
"form_answerType_error": "Silakan pilih cara menjawab formulir",
|
||||
"error_positiveNumber": "Silakan masukkan angka positif",
|
||||
"admin_cat_admins": "Administrator",
|
||||
"admin_admin": "Admin",
|
||||
"admin_listAdminsTitle": "Administrator saat ini",
|
||||
"admin_listAdminsHint": "Tampilkan dan hapus administrator",
|
||||
"admin_addAdminsTitle": "Tambahkan administrator",
|
||||
"admin_addAdminsAdd": "Promosikan kontak sebagai admin",
|
||||
"admin_errorAddKeyLabel": "Tambahkan kunci publik yang valid",
|
||||
"admin_errorAddAdmins": "Pilih kontak untuk dipromosikan sebagai admin",
|
||||
"admin_listName": "Nama admin",
|
||||
"admin_listKey": "Kunci admin",
|
||||
"admin_listAction": "Hapus hak admin",
|
||||
"admin_listHardcoded": "Admin ditambahkan ke config.js. Hanya dapat dihapus dengan menyunting berkas konfig.",
|
||||
"addItemBottom": "Tambahkan kartu ke bawah papan",
|
||||
"addItemTop": "Tambahkan kartu ke atas papan",
|
||||
"moveItemLeft": "Pindahkan item ke kiri",
|
||||
"moveItemRight": "Pindahkan item ke kanan",
|
||||
"kanban_moveBoardLeft": "Pindahkan papan ke kiri",
|
||||
"kanban_moveBoardRight": "Pindahkan papan ke kanan",
|
||||
"moveItemUp": "Pindahkan item ke atas",
|
||||
"moveItemDown": "Pindahkan item ke bawah",
|
||||
"toggleDrag": "Tarik untuk memindahkan item",
|
||||
"profile_remove_avatar": "Hapus avatar ini",
|
||||
"team_autoTrim": "Memangkas riwayat drive tim... Silakan tunggu.",
|
||||
"admin_mfa_confirm_enable": "Apakah Anda yakin ingin mengaktifkan Autentikasi Multi-Faktor?",
|
||||
"admin_mfa_confirm_disable": "Apakah Anda yakin ingin menonaktifkan Autentikasi Multi-Faktor?",
|
||||
"badges_moderator": "Bantuan dan moderasi",
|
||||
"badges_admin": "Administrator",
|
||||
"badges_premium": "Pelanggan",
|
||||
"badges_error": "Kesalahan validasi",
|
||||
"profile_badges": "Lencana",
|
||||
"show_password": "Tampilkan kata sandi",
|
||||
"hide_password": "Sembunyikan kata sandi",
|
||||
"page_previous": "Halaman sebelumnya",
|
||||
"page_next": "Halaman berikutnya",
|
||||
"contact_mastodon": "Mastodon",
|
||||
"contact_forum": "Forum",
|
||||
"settings_profileAvatarLabel": "Avatar",
|
||||
"settings_profileHeaderTitle": "Informasi profil",
|
||||
"settings_profileHeaderHint": "Pilih apa saja tentang akun Anda yang dapat dilihat oleh orang lain",
|
||||
"toolbar_text_tools": "Peralatan teks",
|
||||
"toolbar_show_text_tools": "Tampilkan peralatan teks",
|
||||
"toolbar_hide_text_tools": "Sembunyikan peralatan teks",
|
||||
"fc_open_formaud": "Buka (sebagai pengaudit)",
|
||||
"help_close_button": "Tutup notifikasi bantuan"
|
||||
}
|
||||
|
||||
@ -1825,5 +1825,6 @@
|
||||
"admin_addAdminsHint": "Aggiungi amministratori/trici tramite la loro chiave pubblica o dalla tua lista contatti",
|
||||
"admin_addAdminsAdd": "Promuovi un contatto ad amministratore/trice",
|
||||
"toggleArrows": "Pulsanti freccia per spostare gli elementi",
|
||||
"oo_unstableMigrationWarning": "L'importazione e l'esportazione di alcuni formati OpenDocument (.odt, .odp) è attualmente instabile. Si consiglia di utilizzare altri formati quando possibile. CryptPad tenterà ora una conversione."
|
||||
"oo_unstableMigrationWarning": "L'importazione e l'esportazione di alcuni formati OpenDocument (.odt, .odp) è attualmente instabile. Si consiglia di utilizzare altri formati quando possibile. CryptPad tenterà ora una conversione.",
|
||||
"settings_profileHeaderTitle": "Informazioni del profilo"
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@
|
||||
"settings_save": "保存",
|
||||
"profile_viewMyProfile": "自分のプロフィールを表示",
|
||||
"clickToEdit": "クリックして編集",
|
||||
"profile_addLink": "あなたのウェブサイトへのリンクを追加",
|
||||
"profile_addLink": "あなたのウェブサイトへのリンク",
|
||||
"shareSuccess": "リンクをクリップボードにコピーしました",
|
||||
"shareButton": "共有",
|
||||
"login_hashing": "パスワードをハッシュ化しています。この処理には時間がかかる場合があります。",
|
||||
@ -144,7 +144,7 @@
|
||||
"saved": "保存済",
|
||||
"error": "エラー",
|
||||
"deleted": "削除しました",
|
||||
"profile_editDescription": "説明文を編集",
|
||||
"profile_editDescription": "プロフィールの説明文",
|
||||
"profile_addDescription": "説明文を追加",
|
||||
"profileButton": "プロフィール",
|
||||
"profile_upload": " 新しいアバターをアップロード",
|
||||
@ -1818,5 +1818,27 @@
|
||||
"admin_errorAddKeyLabel": "正しい公開鍵を追加してください",
|
||||
"skipLink": "メインの内容にスキップ",
|
||||
"addItemTop": "カードをボードの最上部に追加",
|
||||
"profile_remove_avatar": "このアバターを削除"
|
||||
"profile_remove_avatar": "このアバターを削除",
|
||||
"oo_couldNotConvertDocument": "ドキュメントの変換に失敗しました。現在はMicrosoft Officeのフォーマット(.docx, .xlsx, .pptx)がインポートとエクスポートに最もよく対応しています。",
|
||||
"oo_unstableMigrationWarning": "現在、一部のOpenDocumentのフォーマット(.odt, .odp)のインポートとエクスポートは不安定です。可能な場合は他のフォーマットを使用することを推奨します。これから、可能な範囲での変換を試みます。",
|
||||
"badges_moderator": "サポートとモデレート",
|
||||
"badges_admin": "管理者",
|
||||
"badges_premium": "定額利用のユーザー",
|
||||
"badges_error": "検証エラー",
|
||||
"profile_badges": "バッジ",
|
||||
"show_password": "パスワードを表示",
|
||||
"hide_password": "パスワードを表示しない",
|
||||
"page_previous": "前のページ",
|
||||
"page_next": "次のページ",
|
||||
"settings_profileHeaderHint": "アカウントの画面に表示するものを選択してください",
|
||||
"contact_mastodon": "Mastodon",
|
||||
"contact_forum": "フォーラム",
|
||||
"settings_profileAvatarLabel": "アバター",
|
||||
"settings_profileHeaderTitle": "プロフィールの情報",
|
||||
"toolbar_text_tools": "テキストツール",
|
||||
"toolbar_show_text_tools": "テキストツールを表示",
|
||||
"toolbar_hide_text_tools": "テキストツールを表示しない",
|
||||
"help_close_button": "ヘルプの通知を閉じる",
|
||||
"admin_documentsDeletionTitle": "複数のドキュメントをアーカイブ",
|
||||
"admin_documentsDeletionHint": "IDをリストの形式で指定してドキュメントをアーカイブ(1行に1つのドキュメントを指定してください)"
|
||||
}
|
||||
|
||||
@ -899,8 +899,8 @@
|
||||
"isContact": "{0} - один из Ваших контактов",
|
||||
"profile_friendRequestSent": "Запрос на контакт ожидает рассмотрения ...",
|
||||
"profile_info": "Другие пользователи могут найти ваш профиль через ваш аватар в списках пользователей документов.",
|
||||
"profile_addLink": "Добавьте ссылку на свой вебсайт",
|
||||
"profile_editDescription": "Изменить описание",
|
||||
"profile_addLink": "Ссылка на Ваш вебсайт",
|
||||
"profile_editDescription": "Описание профиля",
|
||||
"profile_addDescription": "Добавить описание",
|
||||
"notifications_empty": "Нет доступных уведомлений",
|
||||
"friendRequest_notification": "<b>{0}</b> отправил(а) Вам запрос на контакт",
|
||||
@ -1820,5 +1820,26 @@
|
||||
"moveItemDown": "Переместить элемент ниже",
|
||||
"profile_remove_avatar": "Удалить этот аватар",
|
||||
"oo_couldNotConvertDocument": "Не удалось сконвертировать документ. Обратите внимание, что форматы Microsoft Office (.docx, .xlsx, .pptx) в настоящее время дают наилучшие результаты для импорта и экспорта.",
|
||||
"oo_unstableMigrationWarning": "Импорт и экспорт некоторых форматов OpenDocument (.odt, .odp) в настоящее время нестабильны. Мы рекомендуем использовать другие форматы, где это возможно. Сейчас CryptPad попытается выполнить преобразование как можно лучше."
|
||||
"oo_unstableMigrationWarning": "Импорт и экспорт некоторых форматов OpenDocument (.odt, .odp) в настоящее время нестабильны. Мы рекомендуем использовать другие форматы, где это возможно. Сейчас CryptPad попытается выполнить преобразование как можно лучше.",
|
||||
"badges_moderator": "Поддержка и модерация",
|
||||
"badges_admin": "Администратор",
|
||||
"badges_premium": "Подписчик",
|
||||
"badges_error": "Ошибка валидации",
|
||||
"profile_badges": "Значок",
|
||||
"show_password": "Показать пароль",
|
||||
"hide_password": "Скрыть пароль",
|
||||
"page_previous": "Предыдущая страница",
|
||||
"page_next": "Следующая страница",
|
||||
"settings_profileHeaderHint": "Выберите, что другие пользователи видят о Вашем аккаунте",
|
||||
"contact_mastodon": "Mastodon",
|
||||
"contact_forum": "Форум",
|
||||
"settings_profileAvatarLabel": "Аватар",
|
||||
"settings_profileHeaderTitle": "Информация профиля",
|
||||
"toolbar_text_tools": "Инструменты для работы с текстом",
|
||||
"toolbar_show_text_tools": "Показать текстовые инструменты",
|
||||
"toolbar_hide_text_tools": "Скрыть текстовые инструменты",
|
||||
"help_close_button": "Закрыть уведомление о помощи",
|
||||
"fc_open_formaud": "Открыть (как аудитор)",
|
||||
"admin_documentsDeletionTitle": "Архивировать несколько документов",
|
||||
"admin_documentsDeletionHint": "Архивировать несколько документов, используя их идентификаторы (по одному идентификатору документа в строке)"
|
||||
}
|
||||
|
||||
@ -1837,5 +1837,9 @@
|
||||
"settings_profileAvatarLabel": "头像",
|
||||
"toolbar_text_tools": "文本工具",
|
||||
"toolbar_show_text_tools": "显示文本工具",
|
||||
"toolbar_hide_text_tools": "隐藏文本工具"
|
||||
"toolbar_hide_text_tools": "隐藏文本工具",
|
||||
"fc_open_formaud": "打开(作为审计者)",
|
||||
"help_close_button": "关闭帮助通知",
|
||||
"admin_documentsDeletionTitle": "归档多个文档",
|
||||
"admin_documentsDeletionHint": "使用文档 ID 归档文档列表(每行一个文档 ID)"
|
||||
}
|
||||
|
||||
2
www/common/worker.bundle.min.js
vendored
2
www/common/worker.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
@ -63,9 +63,11 @@ define([
|
||||
|
||||
var onDrawioInit = function() {
|
||||
drawIoInitalized = true;
|
||||
var readOnly = framework.isReadOnly() || framework.isLocked();
|
||||
var grid = readOnly ? 0 : 1;
|
||||
lastContent.mxfile.diagram.mxGraphModel._grid = grid;
|
||||
if (lastContent?.mxfile?.diagram?.mxGraphModel) {
|
||||
let readOnly = framework.isReadOnly() || framework.isLocked();
|
||||
let grid = readOnly ? 0 : 1;
|
||||
lastContent.mxfile.diagram.mxGraphModel._grid = grid;
|
||||
}
|
||||
var xmlStr = DiagramUtil.jsonContentAsXML(lastContent);
|
||||
postMessageToDrawio({
|
||||
action: 'load',
|
||||
|
||||
@ -191,9 +191,6 @@
|
||||
position: relative;
|
||||
.cp-markdown-toggle-button {
|
||||
.markdown-toolbar-button-style();
|
||||
&.cp-toolbar-button-active {
|
||||
//background-color: transparent !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -869,7 +866,6 @@
|
||||
}
|
||||
.cp-markdown-toolbar {
|
||||
display: block;
|
||||
padding: 0.1rem 0;
|
||||
border-radius: @variables_radius 0;
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
|
||||
@ -177,12 +177,6 @@
|
||||
background-color: transparent;
|
||||
color: @cp_kanban-fg;
|
||||
border-radius: @variables_radius @variables_radius 0px 0px;
|
||||
button {
|
||||
&:hover {
|
||||
background-color: @cp_kanban-fg;
|
||||
color: @cp_kanban-conflict-bg;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
outline: 0;
|
||||
border-radius: @variables_radius;
|
||||
|
||||
@ -447,6 +447,7 @@ define([
|
||||
APP.getEdPublic = function () {
|
||||
var metadataMgr = APP.common.getMetadataMgr();
|
||||
var privateData = metadataMgr.getPrivateData();
|
||||
const data = APP._lastUpdate;
|
||||
var url = Hash.getPublicSigningKeyString(privateData.origin, data.name, data.edPublic);
|
||||
Clipboard.copy(url, (err) => {
|
||||
if (!err) { UI.log(Messages.genericCopySuccess); }
|
||||
|
||||
@ -326,6 +326,9 @@
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
* {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
.cp-markdown-toggle-button {
|
||||
.markdown-toolbar-button-style();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user