mirror of
https://github.com/wekan/wekan.git
synced 2026-11-08 03:22:32 -05:00
(Arabic and its variants, Persian/Farsi, Hebrew, Uyghur, Uzbek-Arabic and Yiddish — the languages flagged `rtl: true` in `imports/i18n/languages.js`). Previously only some pages flipped. The root `<html>` element now gets a reactive `dir="rtl"`/`dir="ltr"` attribute that follows the chosen language, so the whole UI mirrors at once. To make this work on every page rather than a handful, all directional component CSS was converted to CSS logical properties (`margin-left`→`margin-inline-start`, `left:`→`inset-inline-start:`, `text-align: left`→`text-align: start`, `float: left`→`float: inline-start`, and the mirror-image right/end variants) across 48 stylesheets, which flip automatically with `dir`. Horizontal-centering rules using `left: 50%` + `transform: translate(-50%, …)` were intentionally kept physical, since those already center correctly in both directions. The calendar view also renders RTL. Thanks to xet7 and Claude. - Tests for the RTL UI. A fast, server-less `tests/rtl.test.js` (run with `node tests/rtl.test.js`) checks that exactly the expected languages are flagged `rtl: true`, that the direction helper maps each language to the right `dir` value, that the root `<html>` and the client keep `dir` in sync, and — as a regression guard — that component CSS keeps using logical properties (no physical `margin-left`/`float: left`/bare `left:` offsets sneak back in). A Playwright browser spec `tests/playwright/specs/18-rtl-layout.e2e.js` drives the app in both English (LTR) and Arabic (RTL) and asserts, on the boards list, board view, card details, my-cards / due-cards / global-search, the admin settings page and the login page, that the direction is correct, the translated text is visible, and leading-edge content (the boards menu, the first board list) sits on the correct side. Thanks to xet7 and Claude. - Fixed the "Meteor unit tests" CI job hanging until its 45-minute timeout. The workflow set `TEST_WATCH: '0'`, but meteortesting:mocha computes `testWatch: TEST_WATCH || …` and the string `'0'` is truthy in JavaScript, so it turned on watch mode and the process never exited. Removing the env var lets `meteor test --once` finish and exit with the correct status. Thanks to xet7 and Claude ! Fixes #6136, fixes #3376, fixes #884
243 lines
5.3 KiB
CSS
243 lines
5.3 KiB
CSS
.move-attachment-buttons {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
|
|
.attachments-content .move-compact-section,
|
|
.setting-content .content-body .main-body .form-group .compact-block {
|
|
margin: 16px 0;
|
|
padding: 12px;
|
|
border: 1px solid #d0d7de;
|
|
border-radius: 6px;
|
|
background: #fff8e1;
|
|
max-width: 650px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.attachments-content .move-compact-section p,
|
|
.setting-content .content-body .main-body .form-group .compact-block p {
|
|
max-width: 100%;
|
|
white-space: normal;
|
|
word-wrap: break-word;
|
|
}
|
|
|
|
.attachments-content .move-compact-section h4,
|
|
.setting-content .content-body .main-body h4 {
|
|
margin: 0 0 6px;
|
|
font-size: 1em;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.attachments-content .compact-result-list,
|
|
.setting-content .content-body .main-body .compact-result-list {
|
|
margin: 6px 0 0;
|
|
padding-inline-start: 20px;
|
|
font-size: 0.85em;
|
|
font-family: monospace;
|
|
}
|
|
|
|
.attachments-content .move-progress-section {
|
|
margin: 12px 0 16px;
|
|
padding: 12px;
|
|
border: 1px solid #d0d7de;
|
|
border-radius: 6px;
|
|
background: #f6f8fa;
|
|
}
|
|
|
|
.attachments-content .move-progress-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.attachments-content .move-progress-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
}
|
|
|
|
.attachments-content .move-progress-counter {
|
|
font-weight: 600;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.attachments-content .move-progress-filename {
|
|
font-size: 0.85em;
|
|
color: #57606a;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.attachments-content .move-progress-bar-track {
|
|
background: #dde1e4;
|
|
border-radius: 4px;
|
|
height: 8px;
|
|
overflow: hidden;
|
|
margin: 6px 0;
|
|
}
|
|
|
|
.attachments-content .move-progress-bar-fill {
|
|
background: #1976d2;
|
|
height: 100%;
|
|
border-radius: 4px;
|
|
transition: width 0.4s ease;
|
|
min-width: 2px;
|
|
}
|
|
|
|
.attachments-content .move-progress-bar-indeterminate {
|
|
height: 100%;
|
|
border-radius: 4px;
|
|
background: linear-gradient(90deg, transparent 0%, #1976d2 40%, #42a5f5 60%, transparent 100%);
|
|
background-size: 200% 100%;
|
|
animation: move-progress-slide 1.4s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes move-progress-slide {
|
|
0% { background-position: 200% 0; }
|
|
100% { background-position: -200% 0; }
|
|
}
|
|
|
|
.attachments-content .move-progress-controls {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.attachments-content .move-storage-form {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: 12px;
|
|
flex-wrap: wrap;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.attachments-content .move-storage-selects {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: 12px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.attachments-content .move-storage-form .form-group {
|
|
margin: 0;
|
|
}
|
|
|
|
.attachments-content .move-storage-form .form-group label {
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.attachments-content .move-attachment-buttons button,
|
|
.attachments-content .board-attachments td button {
|
|
background-color: #1976d2;
|
|
border: 1px solid #1565c0;
|
|
color: #fff;
|
|
}
|
|
|
|
.attachments-content .move-attachment-buttons button:hover,
|
|
.attachments-content .board-attachments td button:hover {
|
|
background-color: #1565c0;
|
|
color: #fff;
|
|
}
|
|
|
|
.attachments-content hr {
|
|
height: 0px;
|
|
border: 1px solid #000;
|
|
}
|
|
|
|
|
|
.setting-content .content-body .main-body .storage-rw-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 24px;
|
|
margin-bottom: 12px;
|
|
padding: 6px 0;
|
|
}
|
|
|
|
.setting-content .content-body .main-body .storage-rw-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.setting-content .content-body .main-body .storage-rw-row input[type="checkbox"] {
|
|
position: static;
|
|
inset-inline-start: auto;
|
|
visibility: visible;
|
|
display: inline-block;
|
|
width: 16px;
|
|
height: 16px;
|
|
margin: 0;
|
|
flex-shrink: 0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.setting-content .content-body .main-body .storage-rw-row input[type="checkbox"]:disabled {
|
|
cursor: default;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.setting-content .content-body .main-body .storage-rw-row label {
|
|
margin: 0;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.setting-content .content-body .main-body .storage-rw-row input[type="checkbox"]:disabled + label {
|
|
cursor: default;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.setting-content .content-body .main-body .gridfs-stats-table {
|
|
border-collapse: collapse;
|
|
margin-top: 12px;
|
|
width: auto !important;
|
|
min-width: 0 !important;
|
|
}
|
|
|
|
.setting-content .content-body .main-body .gridfs-stats-table th,
|
|
.setting-content .content-body .main-body .gridfs-stats-table td {
|
|
border: 1px solid #d0d7de;
|
|
padding: 6px 8px;
|
|
text-align: start;
|
|
white-space: nowrap;
|
|
min-width: 0 !important;
|
|
}
|
|
|
|
/* Cloud storage (S3 / Azure / GCS): example value shown below each input. */
|
|
.attachments-content .cloud-input-example {
|
|
display: block;
|
|
color: #888;
|
|
font-size: 0.82em;
|
|
font-family: monospace;
|
|
word-break: break-all;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
/* Cloud storage: where-to-find-this-value path shown below the example. */
|
|
.attachments-content .cloud-input-path {
|
|
display: block;
|
|
color: #6a737d;
|
|
font-size: 0.82em;
|
|
line-height: 1.4;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* Cloud storage: translated label shown under the (English) label. */
|
|
.attachments-content .cloud-input-label-tr {
|
|
display: block;
|
|
color: #57606a;
|
|
font-size: 0.9em;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
/* Cloud storage: description text (English literal and translated). */
|
|
.attachments-content .cloud-input-desc {
|
|
display: block;
|
|
color: #6a737d;
|
|
font-size: 0.82em;
|
|
line-height: 1.4;
|
|
margin-top: 2px;
|
|
}
|