mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 01:20:07 -05:00
Card Settings: a checkbox per section, always every field, only in Board Settings.
Card Settings is now only Board Settings / Card. The opened card has no Card Settings button any more: it simply shows every field its board shows on cards, empty or not. - On this card, Show empty and Show empty fields are removed, with the hamburgers' Select all / Select none rows, their handlers, helpers, board methods (setCardFieldAlwaysShown, setShowEmptyCardFields), CSS and the three translation keys. The card no longer reads its own shownFields / hiddenFields, nor the board's cardFieldsAlwaysShown / showEmptyCardFields; the schema keeps them so old documents validate. - Every section has a checkbox before its title: whether the whole section is shown on the chosen side, whatever its rows are ticked. Stored per side in cardSettingsHiddenOnCard / cardSettingsHiddenOnMinicard (setCardSettingsSectionShown, board admins). The opened card's view of the board and a new minicard view read false for every row of a hidden section, Scrum fields included; Card Settings itself reads the raw board, so the rows keep their ticks. - A section with one row on the chosen side is one line: one checkbox, the name, one hamburger. - A hamburger is drawn only when it holds something. - Custom Fields: its items are the board's custom fields, in their sort order, reordered by drag and drop within the section, with a + under them that creates one. Show on Minicard sets a field's showOnCard, Show on Card its alwaysOnCard; its hamburger edits the field. The section's checkbox is the board's Custom Fields flag of that side. - Card actions (Filter: Subtasks, Edit voting, Card kind, ...) live in the card's own section hamburgers; Card Settings keeps only board actions. Docs: docs/Features/Cards/Card-Settings.md replaces Card-Settings-On-Card.md; Card-Fields.md and Board Settings / Card.md rewritten. New tests cardSettingsSectionShown and cardSettingsCustomFields; the guards of the removed behaviour say why they changed; card-add-fields.e2e.js covers section hiding per side, an empty card showing every field, empty hamburgers, the one-row line, the Custom Fields items and +, and that the opened card has no Card Settings. Thanks to xet7 !
This commit is contained in:
1 parent
039935dd0b
commit
3e5bc58105
285 files changed
+2243
-2976
No files matched your search
@@ -52,8 +52,14 @@ const boardFor = context => ReactiveCache.getBoard(context?.record?.boardId || S
|
||||
// `field` (a definition suffix, 'Sprint') draws one field alone: on a card and
|
||||
// a minicard each Scrum field sits where the board's Board Settings / Card
|
||||
// order puts it (models/lib/cardFieldOrder.js SCRUM_FIELD_KEYS).
|
||||
// Read through the board as that side sees it (models/lib/cardShownFields.js
|
||||
// boardForSide): a Scrum section hidden whole on Show on Card or Show on
|
||||
// Minicard in Card Settings hides these fields there too. The settings above
|
||||
// (scrumFieldSettings) read the board itself.
|
||||
function visibleFields(context) {
|
||||
const board = boardFor(context);
|
||||
const { boardForSide } = require('/models/lib/cardShownFields');
|
||||
const side = context?.kind === 'card' || context?.kind === 'minicard' ? context.kind : null;
|
||||
const board = side ? boardForSide(boardFor(context), side) : boardFor(context);
|
||||
return (definitions[context?.kind] || []).filter(([suffix]) => (!context.field || context.field === suffix) &&
|
||||
board?.scrum?.visibility?.[`${context.kind}${suffix}`] === true);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,6 @@
|
||||
/* "Card Settings" on the opened card (docs/Features/Cards/Card-Settings-On-Card.md):
|
||||
it replaces itself, and everything below it, with Card Settings on the card. */
|
||||
.card-details-add-fields { padding: 4px 0 2px; }
|
||||
.card-details-add-fields-button { display: inline-flex; align-items: center; gap: 0.3em; padding: 2px 8px; border-radius: 3px; }
|
||||
.card-details-add-fields-button:hover { background: rgba(0, 0, 0, 0.06); }
|
||||
|
||||
/* Card Settings on the card: the title with its X at the end of the line,
|
||||
/* Card Settings (Board Settings / Card, docs/Features/Cards/Card-Settings.md):
|
||||
"Show" and its two choices, then the sections drawn like checklists. */
|
||||
.card-settings-inline { padding: 4px 0 8px; }
|
||||
.card-settings-inline-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.card-settings-inline-title { flex: 1 1 auto; margin: 0; }
|
||||
.card-settings-inline-close {
|
||||
padding: 2px 8px;
|
||||
border-radius: 3px;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.card-settings-inline-close:hover,
|
||||
.card-settings-inline-close:focus-visible { background: rgba(0, 0, 0, 0.06); }
|
||||
.card-settings-inline-show {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -78,8 +58,33 @@
|
||||
.card-settings-inline-collapse:focus-visible,
|
||||
.card-settings-inline-menu:hover,
|
||||
.card-settings-inline-menu:focus-visible { color: #2980b9; }
|
||||
/* The section's own checkbox, left of its title: the rows' look. A section
|
||||
hidden whole on this side keeps its rows' ticks, drawn faded. */
|
||||
.card-settings-section-side { flex: 0 0 auto; }
|
||||
.card-settings-section-side > a.flex { margin: 0; }
|
||||
.card-settings-inline-section.is-section-hidden .card-settings-inline-items { opacity: 0.55; }
|
||||
/* One row on this side: one line, no caret - its checkbox where the other
|
||||
sections' checkboxes are. */
|
||||
.card-settings-inline-section.is-single .card-settings-inline-section-head {
|
||||
padding-inline-start: calc(0.5em + 8px);
|
||||
}
|
||||
/* "+" under Custom Fields' items: a new custom field. */
|
||||
.card-settings-add-custom-field { padding: 2px 0 0 22px; }
|
||||
.card-settings-add-custom-field-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 28px;
|
||||
min-height: 28px;
|
||||
border-radius: 3px;
|
||||
color: #808080;
|
||||
text-decoration: none;
|
||||
}
|
||||
.card-settings-add-custom-field-button:hover,
|
||||
.card-settings-add-custom-field-button:focus-visible { background: rgba(0, 0, 0, 0.06); color: #2980b9; }
|
||||
/* Collapsed: the items hidden, not removed, so their drag stays bound. */
|
||||
.card-settings-inline-section.is-collapsed .card-settings-inline-items { display: none; }
|
||||
.card-settings-inline-section.is-collapsed .card-settings-inline-items,
|
||||
.card-settings-inline-section.is-collapsed .card-settings-add-custom-field { display: none; }
|
||||
|
||||
/* An item: the checkbox, the name, and its hamburger at the end
|
||||
(sidebar.css .card-settings-line is the line itself). */
|
||||
@@ -100,14 +105,6 @@
|
||||
.card-settings-item-menu .is-animating .materialCheckBox { transition: 0.2s; }
|
||||
|
||||
/* The hamburgers' popups. */
|
||||
.card-settings-section-menu .card-settings-section-menu-select {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 4px 8px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
.card-settings-item-menu,
|
||||
.card-settings-section-menu { min-width: 16em; }
|
||||
/* The hamburgers' checkboxes: a space's width before their label, as on
|
||||
|
||||
@@ -1,66 +1,23 @@
|
||||
import './cardDetails.jade';
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { Utils } from '/client/lib/utils';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
|
||||
// docs/Features/Cards/Card-Fields.md: an opened card shows only the fields it
|
||||
// has data in - and what its board always shows (by default its description,
|
||||
// attachments and comments), empty or not - and "+ Add" chooses the rest. The rules are models/lib/cardShownFields.js.
|
||||
// docs/Features/Cards/Card-Fields.md: an opened card shows every field its
|
||||
// board shows on cards, empty or not, less the Card Settings sections the
|
||||
// board hides on Show on Card. The rules are models/lib/cardShownFields.js.
|
||||
const f = require('/models/lib/cardShownFields');
|
||||
|
||||
// What lives in other collections, for "has data".
|
||||
function countOf(list) {
|
||||
if (!list) return 0;
|
||||
if (typeof list.length === 'number') return list.length;
|
||||
return typeof list.count === 'function' ? list.count() : 0;
|
||||
}
|
||||
|
||||
export function cardFieldCounts(card) {
|
||||
if (!card || !card._id) return {};
|
||||
return {
|
||||
checklists: typeof card.checklists === 'function' ? countOf(card.checklists()) : 0,
|
||||
subtasks: typeof card.subtasks === 'function' ? countOf(card.subtasks()) : 0,
|
||||
textNotes: countOf(ReactiveCache.getCardTextNotes({ cardId: card._id })),
|
||||
// For a board that does not always show these: shown when there are some.
|
||||
attachments: typeof card.attachments === 'function' ? countOf(card.attachments()) : 0,
|
||||
comments: typeof card.comments === 'function' ? countOf(card.comments()) : 0,
|
||||
};
|
||||
}
|
||||
|
||||
// The card's document, with its methods, for a template's data.
|
||||
function cardOf(data) {
|
||||
if (!data || !data._id) return null;
|
||||
return ReactiveCache.getCard(data._id) || data;
|
||||
}
|
||||
|
||||
// What decides which fields `card` shows: its DATA, which a linked card keeps
|
||||
// on its source card (members, labels, dates, custom fields, checklists ...),
|
||||
// and its own choices (shownFields / hiddenFields, set on the card opened).
|
||||
// Reading the linked card's own empty document hid every field its source
|
||||
// has (the #1946/#6613 browser test). Returns { card, counts }.
|
||||
export function shownFieldsOf(card) {
|
||||
if (!card) return { card: null, counts: {} };
|
||||
const real = typeof card.getRealCard === 'function' ? (card.getRealCard() || card) : card;
|
||||
if (real === card) return { card, counts: cardFieldCounts(card) };
|
||||
return {
|
||||
card: { ...real, shownFields: card.shownFields, hiddenFields: card.hiddenFields },
|
||||
counts: cardFieldCounts(real),
|
||||
};
|
||||
}
|
||||
|
||||
// The board as this card sees it (cardShownFields.js boardForCard).
|
||||
export function cardBoardView(data) {
|
||||
const board = Utils.getCurrentBoard();
|
||||
const card = cardOf(data);
|
||||
if (!board || !card || card.boardId !== board._id) return board;
|
||||
const view = shownFieldsOf(card);
|
||||
return f.boardForCard(board, view.card, view.counts);
|
||||
// The board as its opened cards see it (cardShownFields.js boardForCard): the
|
||||
// same for every card of the board, empty or not, so `data` (the card) does
|
||||
// not change it - it is kept so the callers read as before.
|
||||
export function cardBoardView(data) { // eslint-disable-line no-unused-vars
|
||||
return f.boardForCard(Utils.getCurrentBoard());
|
||||
}
|
||||
|
||||
// The opened card and each of its section templates read `currentBoard`; this
|
||||
// template-level helper answers before the global one, so every
|
||||
// `currentBoard.allowsX` in them asks this card's view - and a template not
|
||||
// listed here (the minicard, the board) is unchanged.
|
||||
// `currentBoard.allowsX` in them asks the card's view - and a template not
|
||||
// listed here (the board, Card Settings itself) is unchanged. The minicard has
|
||||
// its own (client/components/cards/minicard.js MINICARD_FIELD_TEMPLATES).
|
||||
export const CARD_FIELD_TEMPLATES = Object.freeze([
|
||||
'cardDetails', 'cardFieldSectionLabels', 'cardFieldSectionDates', 'cardFieldSectionMembers',
|
||||
'cardFieldSectionDependencies', 'cardFieldSectionSort', 'cardFieldSectionCustomFields',
|
||||
@@ -74,46 +31,3 @@ CARD_FIELD_TEMPLATES.forEach(name => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Whether this card shows the field `key` - for a section with no board flag
|
||||
// of its own to read (the Scrum fields, cardDetails.js orderedCardFieldSections).
|
||||
export function cardShowsField(data, key) {
|
||||
const card = cardOf(data);
|
||||
if (!card) return true;
|
||||
const view = shownFieldsOf(card);
|
||||
return f.isShown(key, view.card, view.counts, Utils.getCurrentBoard());
|
||||
}
|
||||
|
||||
// "Card Settings" on the opened card: the button and everything below it are
|
||||
// replaced by Card Settings itself, on the card (cardSettingsInline,
|
||||
// client/components/sidebar/sidebar.jade) - its sections as checklists, their
|
||||
// rows as checklist items - until its X closes it. The id of the card it is
|
||||
// open on; a card opened next has it closed.
|
||||
const cardSettingsOpenOn = new ReactiveVar(null);
|
||||
|
||||
export function isCardSettingsOpen(cardId) {
|
||||
return Boolean(cardId) && cardSettingsOpenOn.get() === cardId;
|
||||
}
|
||||
|
||||
export function closeCardSettings() {
|
||||
cardSettingsOpenOn.set(null);
|
||||
}
|
||||
|
||||
Template.cardDetails.helpers({
|
||||
cardSettingsOpen() {
|
||||
return isCardSettingsOpen(this && this._id);
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardDetails.onDestroyed(function () {
|
||||
if (isCardSettingsOpen(this.data && this.data._id)) closeCardSettings();
|
||||
});
|
||||
|
||||
Template.cardDetails.events({
|
||||
'click .js-open-card-add-fields'(event) {
|
||||
event.preventDefault();
|
||||
const card = cardOf(Template.currentData());
|
||||
if (!card) return;
|
||||
cardSettingsOpenOn.set(card._id);
|
||||
},
|
||||
});
|
||||
@@ -159,169 +159,158 @@ template(name="cardDetails")
|
||||
.card-details-cover
|
||||
img.card-details-cover-image(alt="" src="{{attachmentPreviewUrl cover}}?dummyReloadAfterSessionEstablished={{sess}}" width="512" height="180" decoding="async")
|
||||
|
||||
//- "Card Settings", under the cover: the card shows only the fields it has
|
||||
data in - and its description, attachments and comments, empty or not -
|
||||
and Card Settings chooses the rest. Opened, it REPLACES the button and
|
||||
everything below it with Card Settings itself (cardSettingsInline,
|
||||
client/components/sidebar/sidebar.jade) until its X closes it
|
||||
(docs/Features/Cards/Card-Settings-On-Card.md).
|
||||
if cardSettingsOpen
|
||||
+cardSettingsInline(card=this)
|
||||
else
|
||||
if canModifyCard
|
||||
.card-details-add-fields
|
||||
a.card-details-add-fields-button.js-open-card-add-fields(href="#" role="button" aria-expanded="false" title="{{_ 'card-settings'}}" aria-label="{{_ 'card-settings'}}")
|
||||
i.fa.fa-cog(aria-hidden="true")
|
||||
| {{_ 'card-settings'}}
|
||||
//- Every field the board shows on cards, empty or not
|
||||
(docs/Features/Cards/Card-Fields.md). Which ones is Board Settings / Card
|
||||
(docs/Features/Cards/Card-Settings.md) - the opened card has no Card
|
||||
Settings of its own.
|
||||
.card-details-left
|
||||
|
||||
.card-details-left
|
||||
//- At risk, Show on Card (docs/Features/Cards/At-Risk.md): every reason
|
||||
that applied, the moves back included.
|
||||
unless $eq currentBoard.allowsAtRiskOnCard false
|
||||
with cardAtRisk
|
||||
.card-details-at-risk.js-card-at-risk
|
||||
i.fa.fa-exclamation-triangle
|
||||
| {{_ 'at-risk'}}: {{text}}
|
||||
|
||||
//- At risk, Show on Card (docs/Features/Cards/At-Risk.md): every reason
|
||||
that applied, the moves back included.
|
||||
unless $eq currentBoard.allowsAtRiskOnCard false
|
||||
with cardAtRisk
|
||||
.card-details-at-risk.js-card-at-risk
|
||||
i.fa.fa-exclamation-triangle
|
||||
| {{_ 'at-risk'}}: {{text}}
|
||||
.card-details-items
|
||||
//- #4448: render the reorderable card-detail sections (Labels, Dates,
|
||||
Members, Dependencies, Sort, Custom Fields, Vote/Poker, Description)
|
||||
in the board's stored order, falling back to the historical fixed
|
||||
order - so a board that never touches the setting renders exactly
|
||||
what it always has. Board Settings / Card writes the order per
|
||||
FIELD; each section renders where its first field is, and the
|
||||
fields inside it (the four dates, the people of Members, ...) in
|
||||
their own order through the ordered*Fields helpers.
|
||||
models/lib/cardFieldOrder.js, client/components/sidebar/sidebar.jade
|
||||
//- `each section in ...`, not `each ...`: the plain form makes the
|
||||
section NAME ("labels", "dates", ...) the data context, so every
|
||||
section template - and every popup opened from one, e.g. the Labels
|
||||
popup - saw a string where it expected the card. Clicking a label
|
||||
then silently did nothing (`card.toggleLabel` was undefined) and
|
||||
the card's own labels/stickers/locations lists rendered empty. The
|
||||
`in` form keeps `this` as the card.
|
||||
each section in orderedCardFieldSections
|
||||
if $eq section "labels"
|
||||
+cardFieldSectionLabels
|
||||
if $eq section "dates"
|
||||
+cardFieldSectionDates
|
||||
if $eq section "members"
|
||||
+cardFieldSectionMembers
|
||||
if $eq section "dependencies"
|
||||
+cardFieldSectionDependencies
|
||||
if $eq section "sort"
|
||||
+cardFieldSectionSort
|
||||
if $eq section "customFields"
|
||||
+cardFieldSectionCustomFields
|
||||
if $eq section "voteAndPoker"
|
||||
+cardFieldSectionVoteAndPoker
|
||||
if $eq section "description"
|
||||
+cardFieldSectionDescription
|
||||
//- Each Scrum field where the board's order puts it ("Scrum settings:
|
||||
Sprint" ... in Board Settings / Card).
|
||||
//- The Scrum fields shown on this card are ONE section, "Scrum
|
||||
settings", headed where the first of them is, with Card kind in its
|
||||
hamburger (docs/Features/Cards/Card-Fields.md).
|
||||
if $eq section firstScrumSection
|
||||
+cardSectionHeader(section="scrum" icon="fa-repeat" label="scrum-settings" menuClass="js-section-card-kind" menuTitle="cardKindPopup-title")
|
||||
if isSectionOpen "scrum"
|
||||
if $eq section "scrumSprint"
|
||||
+cardFieldSectionScrumSprint
|
||||
if $eq section "scrumPastSprints"
|
||||
+cardFieldSectionScrumPastSprints
|
||||
if $eq section "scrumRelease"
|
||||
+cardFieldSectionScrumRelease
|
||||
if $eq section "scrumIssueType"
|
||||
+cardFieldSectionScrumIssueType
|
||||
if $eq section "scrumAcceptanceCriteria"
|
||||
+cardFieldSectionScrumAcceptanceCriteria
|
||||
if $eq section "scrumBacklogRank"
|
||||
+cardFieldSectionScrumBacklogRank
|
||||
|
||||
.card-details-items
|
||||
//- #4448: render the reorderable card-detail sections (Labels, Dates,
|
||||
Members, Dependencies, Sort, Custom Fields, Vote/Poker, Description)
|
||||
in the board's stored order, falling back to the historical fixed
|
||||
order - so a board that never touches the setting renders exactly
|
||||
what it always has. Board Settings / Card writes the order per
|
||||
FIELD; each section renders where its first field is, and the
|
||||
fields inside it (the four dates, the people of Members, ...) in
|
||||
their own order through the ordered*Fields helpers.
|
||||
models/lib/cardFieldOrder.js, client/components/sidebar/sidebar.jade
|
||||
//- `each section in ...`, not `each ...`: the plain form makes the
|
||||
section NAME ("labels", "dates", ...) the data context, so every
|
||||
section template - and every popup opened from one, e.g. the Labels
|
||||
popup - saw a string where it expected the card. Clicking a label
|
||||
then silently did nothing (`card.toggleLabel` was undefined) and
|
||||
the card's own labels/stickers/locations lists rendered empty. The
|
||||
`in` form keeps `this` as the card.
|
||||
each section in orderedCardFieldSections
|
||||
if $eq section "labels"
|
||||
+cardFieldSectionLabels
|
||||
if $eq section "dates"
|
||||
+cardFieldSectionDates
|
||||
if $eq section "members"
|
||||
+cardFieldSectionMembers
|
||||
if $eq section "dependencies"
|
||||
+cardFieldSectionDependencies
|
||||
if $eq section "sort"
|
||||
+cardFieldSectionSort
|
||||
if $eq section "customFields"
|
||||
+cardFieldSectionCustomFields
|
||||
if $eq section "voteAndPoker"
|
||||
+cardFieldSectionVoteAndPoker
|
||||
if $eq section "description"
|
||||
+cardFieldSectionDescription
|
||||
//- Each Scrum field where the board's order puts it ("Scrum settings:
|
||||
Sprint" ... in Board Settings / Card).
|
||||
//- The Scrum fields shown on this card are ONE section, "Scrum
|
||||
settings", headed where the first of them is, with Card kind in its
|
||||
hamburger (docs/Features/Cards/Card-Fields.md).
|
||||
if $eq section firstScrumSection
|
||||
+cardSectionHeader(section="scrum" icon="fa-repeat" label="scrum-settings" menuClass="js-section-card-kind" menuTitle="cardKindPopup-title")
|
||||
if isSectionOpen "scrum"
|
||||
if $eq section "scrumSprint"
|
||||
+cardFieldSectionScrumSprint
|
||||
if $eq section "scrumPastSprints"
|
||||
+cardFieldSectionScrumPastSprints
|
||||
if $eq section "scrumRelease"
|
||||
+cardFieldSectionScrumRelease
|
||||
if $eq section "scrumIssueType"
|
||||
+cardFieldSectionScrumIssueType
|
||||
if $eq section "scrumAcceptanceCriteria"
|
||||
+cardFieldSectionScrumAcceptanceCriteria
|
||||
if $eq section "scrumBacklogRank"
|
||||
+cardFieldSectionScrumBacklogRank
|
||||
.card-checklist-attachmentGalleries
|
||||
.card-checklist-attachmentGallery.card-checklists
|
||||
if currentBoard.allowsChecklists
|
||||
unless $eq currentBoard.allowsChecklistTitle false
|
||||
+cardSectionHeader(section="checklists" icon="fa-check" label="checklists")
|
||||
if checklistSectionOpen
|
||||
//- Total checklist item count (finished/total) shown above all
|
||||
checklists. The board flag is a cheap boolean, so when it is off
|
||||
the checklist counting below is never evaluated.
|
||||
if currentBoard.allowsChecklistCountBadgeOnCard
|
||||
if checklists.length
|
||||
h4.card-details-item-subtitle
|
||||
| {{checklistFinishedCount}}/{{checklistItemCount}}
|
||||
+checklists(cardId = _id card = this)
|
||||
if currentBoard.allowsSubtasks
|
||||
//- #4693: "Subtasks (1/3)", done/total (subtaskDoneCount in subtasks.js).
|
||||
+cardSectionHeader(section="subtasks" icon="fa-sitemap" label="subtasks"
|
||||
count=subtaskDoneCount
|
||||
menuClass="js-open-subtasks-menu" menuTitle="subtasks")
|
||||
if isSectionOpen "subtasks"
|
||||
+subtasks(cardId = _id)
|
||||
if currentBoard.allowsAttachments
|
||||
+cardSectionHeader(section="attachments" icon="fa-paperclip" label="attachments"
|
||||
count=attachmentCount)
|
||||
if isSectionOpen "attachments"
|
||||
//- #6796: the upload rules (size, types, what an invalid name
|
||||
does) are read when uploading, so they are in the upload popup
|
||||
(attachments.jade cardAttachmentsPopup), not above every list.
|
||||
.card-checklist-attachmentGallery.card-attachmentGallery
|
||||
+attachmentGallery
|
||||
|
||||
.card-checklist-attachmentGalleries
|
||||
.card-checklist-attachmentGallery.card-checklists
|
||||
if currentBoard.allowsChecklists
|
||||
unless $eq currentBoard.allowsChecklistTitle false
|
||||
+cardSectionHeader(section="checklists" icon="fa-check" label="checklists")
|
||||
if checklistSectionOpen
|
||||
//- Total checklist item count (finished/total) shown above all
|
||||
checklists. The board flag is a cheap boolean, so when it is off
|
||||
the checklist counting below is never evaluated.
|
||||
if currentBoard.allowsChecklistCountBadgeOnCard
|
||||
if checklists.length
|
||||
h4.card-details-item-subtitle
|
||||
| {{checklistFinishedCount}}/{{checklistItemCount}}
|
||||
+checklists(cardId = _id card = this)
|
||||
if currentBoard.allowsSubtasks
|
||||
//- #4693: "Subtasks (1/3)", done/total (subtaskDoneCount in subtasks.js).
|
||||
+cardSectionHeader(section="subtasks" icon="fa-sitemap" label="subtasks"
|
||||
count=subtaskDoneCount
|
||||
menuClass="js-open-subtasks-menu" menuTitle="subtasks")
|
||||
if isSectionOpen "subtasks"
|
||||
+subtasks(cardId = _id)
|
||||
if currentBoard.allowsAttachments
|
||||
+cardSectionHeader(section="attachments" icon="fa-paperclip" label="attachments"
|
||||
count=attachmentCount)
|
||||
if isSectionOpen "attachments"
|
||||
//- #6796: the upload rules (size, types, what an invalid name
|
||||
does) are read when uploading, so they are in the upload popup
|
||||
(attachments.jade cardAttachmentsPopup), not above every list.
|
||||
.card-checklist-attachmentGallery.card-attachmentGallery
|
||||
+attachmentGallery
|
||||
//- GitHub issue #595: markdown text notes, a card-level collection of
|
||||
small editable markdown blocks - separate from the card's single
|
||||
description - so a card is not limited to cramming everything into
|
||||
one description field. Edited in a popup reusing the SAME editor/
|
||||
viewer widget the description above already uses.
|
||||
if currentBoard.allowsTextNotes
|
||||
+cardSectionHeader(section="text-notes" icon="fa-file-text-o" label="text-notes")
|
||||
if isSectionOpen "text-notes"
|
||||
+cardTextNotes(_id = _id)
|
||||
|
||||
//- GitHub issue #595: markdown text notes, a card-level collection of
|
||||
small editable markdown blocks - separate from the card's single
|
||||
description - so a card is not limited to cramming everything into
|
||||
one description field. Edited in a popup reusing the SAME editor/
|
||||
viewer widget the description above already uses.
|
||||
if currentBoard.allowsTextNotes
|
||||
+cardSectionHeader(section="text-notes" icon="fa-file-text-o" label="text-notes")
|
||||
if isSectionOpen "text-notes"
|
||||
+cardTextNotes(_id = _id)
|
||||
//- Similar cards, Show on Card: the cards of this board like this one
|
||||
(docs/Features/Cards/Similar-Cards.md). Asked when the card opens, and
|
||||
the section is there only when there are some
|
||||
(docs/Features/Cards/Card-Fields.md).
|
||||
unless $eq currentBoard.allowsSimilarCardsOnCard false
|
||||
+cardSimilarCardsSection(cardId=_id)
|
||||
|
||||
//- Similar cards, Show on Card: the cards of this board like this one
|
||||
(docs/Features/Cards/Similar-Cards.md). Asked when the card opens, and
|
||||
the section is there only when there are some
|
||||
(docs/Features/Cards/Card-Fields.md).
|
||||
unless $eq currentBoard.allowsSimilarCardsOnCard false
|
||||
+cardSimilarCardsSection(cardId=_id)
|
||||
//- The comments: in this column, or - on a maximized card - at the top of
|
||||
the right one (cardCommentsSection below).
|
||||
unless cardMaximized
|
||||
+cardCommentsSection
|
||||
|
||||
//- The comments: in this column, or - on a maximized card - at the top of
|
||||
the right one (cardCommentsSection below).
|
||||
unless cardMaximized
|
||||
+cardCommentsSection
|
||||
.card-details-right
|
||||
|
||||
.card-details-right
|
||||
//- A maximized card has its comments here, beside the card's fields.
|
||||
if cardMaximized
|
||||
+cardCommentsSection
|
||||
|
||||
//- A maximized card has its comments here, beside the card's fields.
|
||||
if cardMaximized
|
||||
+cardCommentsSection
|
||||
//- #6688: `allowsActivities` existed in the schema (default true) but
|
||||
gated nothing; Board Settings / Card now has its row and this is what
|
||||
the row hides.
|
||||
if currentBoard.allowsActivities
|
||||
if currentUser.isBoardAdmin
|
||||
//- OUTSIDE .activity-title, which is `display: flex`: a rule inside it
|
||||
becomes a flex item and renders as a short line beside the heading
|
||||
instead of a separator above it.
|
||||
The eye that used to sit here showed and hid exactly what the caret
|
||||
shows and hides, so there were two controls for one thing and they
|
||||
could disagree. The caret is the one that stayed, and this section is
|
||||
the one that starts CLOSED - a card is opened to read the card, not
|
||||
its history.
|
||||
+cardSectionHeader(section="activities" icon="fa-history" label="activities")
|
||||
|
||||
//- #6688: `allowsActivities` existed in the schema (default true) but
|
||||
gated nothing; Board Settings / Card now has its row and this is what
|
||||
the row hides.
|
||||
if currentBoard.allowsActivities
|
||||
if currentUser.isBoardAdmin
|
||||
//- OUTSIDE .activity-title, which is `display: flex`: a rule inside it
|
||||
becomes a flex item and renders as a short line beside the heading
|
||||
instead of a separator above it.
|
||||
The eye that used to sit here showed and hid exactly what the caret
|
||||
shows and hides, so there were two controls for one thing and they
|
||||
could disagree. The caret is the one that stayed, and this section is
|
||||
the one that starts CLOSED - a card is opened to read the card, not
|
||||
its history.
|
||||
+cardSectionHeader(section="activities" icon="fa-history" label="activities")
|
||||
|
||||
if currentUser.isBoardAdmin
|
||||
if isSectionOpen "activities"
|
||||
if isLoaded.get
|
||||
if isLinkedCard
|
||||
+activities(card=this mode="linkedcard")
|
||||
else if isLinkedBoard
|
||||
+activities(card=this mode="linkedboard")
|
||||
else
|
||||
+activities(card=this mode="card")
|
||||
if currentUser.isBoardAdmin
|
||||
if isSectionOpen "activities"
|
||||
if isLoaded.get
|
||||
if isLinkedCard
|
||||
+activities(card=this mode="linkedcard")
|
||||
else if isLinkedBoard
|
||||
+activities(card=this mode="linkedboard")
|
||||
else
|
||||
+activities(card=this mode="card")
|
||||
|
||||
template(name="cardFieldSectionLabels")
|
||||
.card-details-group.card-details-group-labels
|
||||
@@ -722,14 +711,11 @@ template(name="cardFieldSectionSort")
|
||||
//.card-details-items
|
||||
|
||||
template(name="cardFieldSectionCustomFields")
|
||||
//- The heading is here for a card that has a custom field value, or that
|
||||
ticked Custom Fields in "+ Add" (docs/Features/Cards/Card-Fields.md). It
|
||||
used to be on EVERY card the reader may write to, because the hamburger
|
||||
at its end is the single place custom fields live - the picker of which
|
||||
fields are on this card, a pencil each, and "Add custom field" - and a
|
||||
card with none had no other way to get one. "+ Add" is that way now, so
|
||||
a card with none no longer carries an empty heading. The FIELDS below
|
||||
still come from `customFieldsWD`.
|
||||
//- The heading is on EVERY card the reader may write to whose board shows
|
||||
Custom Fields on cards (docs/Features/Cards/Card-Fields.md), empty or not:
|
||||
the hamburger at its end is the single place custom fields live - the
|
||||
picker of which fields are on this card, a pencil each, and "Add custom
|
||||
field". The FIELDS below still come from `customFieldsWD`.
|
||||
if canShowCustomFieldsOnCard
|
||||
//- ONE header for the whole group, outside the loop: a card with six
|
||||
custom fields is one Custom Fields section, not six sections that
|
||||
|
||||
@@ -754,14 +754,15 @@ Template.registerHelper('cardSwimlaneTitle', function cardSwimlaneTitle() {
|
||||
return swimlane && swimlane.title;
|
||||
});
|
||||
|
||||
// The Custom Fields section: on a card that has a custom field value, or that
|
||||
// ticked Custom Fields in "+ Add" (docs/Features/Cards/Card-Fields.md) - not on
|
||||
// every card, where it was an empty heading. "+ Add" is how a card with none
|
||||
// gets the section, and its hamburger then adds the fields.
|
||||
// The Custom Fields section: on every card the reader may change whose board
|
||||
// shows Custom Fields on cards, empty or not (docs/Features/Cards/Card-Fields.md)
|
||||
// - its hamburger is where the fields are added. The board as its cards see it,
|
||||
// so a board that hides the whole Custom Fields section on Show on Card
|
||||
// (models/lib/cardShownFields.js boardForCard) hides it here too.
|
||||
Template.registerHelper('canShowCustomFieldsOnCard', function canShowCustomFieldsOnCard() {
|
||||
const { cardShowsField } = require('/client/components/cards/cardAddFields');
|
||||
const board = this?.board?.();
|
||||
return Utils.canModifyCard(this) && board?.allowsCustomFields !== false && cardShowsField(this, 'customFields');
|
||||
const { boardForCard } = require('/models/lib/cardShownFields');
|
||||
const board = boardForCard(this?.board?.());
|
||||
return Utils.canModifyCard(this) && board?.allowsCustomFields !== false;
|
||||
});
|
||||
|
||||
Template.registerHelper('stickers', function stickers() {
|
||||
@@ -909,13 +910,15 @@ Template.registerHelper('isCurrentListId', function isCurrentListId(listId) {
|
||||
Template.registerHelper('orderedVoteAndPokerFields', sectionHelper('voteAndPoker'));
|
||||
}
|
||||
|
||||
// The card's sections in the board's order, less the Scrum fields this card
|
||||
// does not show - a Scrum field is its own section with no board flag in the
|
||||
// template to read (docs/Features/Cards/Card-Fields.md). The board has to
|
||||
// allow it first (Board Settings / Scrum): Show empty fields and Show empty
|
||||
// only show what the board allows, as they do for Members or Vote (#6830).
|
||||
// The card's sections in the board's order, less the Scrum fields the board
|
||||
// does not show on cards - a Scrum field is its own section with no board flag
|
||||
// in the template to read (docs/Features/Cards/Card-Fields.md). Only what the
|
||||
// board allows (Board Settings / Scrum), as for Members or Vote (#6830); and
|
||||
// read through the board as its cards see it (cardShownFields.js
|
||||
// boardForCard), so a Scrum section hidden whole on Show on Card is gone.
|
||||
function orderedSectionsOf(card) {
|
||||
const board = card?.board?.();
|
||||
const { boardAllows, boardForCard } = require('/models/lib/cardShownFields');
|
||||
const board = boardForCard(card?.board?.());
|
||||
let sections;
|
||||
if (board && typeof board.getCardFieldOrder === 'function') {
|
||||
sections = board.getCardFieldOrder();
|
||||
@@ -923,10 +926,7 @@ function orderedSectionsOf(card) {
|
||||
const { applyCardFieldOrder } = require('/models/lib/cardFieldOrder');
|
||||
sections = applyCardFieldOrder(board?.cardFieldOrder);
|
||||
}
|
||||
const { cardShowsField } = require('/client/components/cards/cardAddFields');
|
||||
const { boardAllows } = require('/models/lib/cardShownFields');
|
||||
return sections.filter(s => !/^scrum[A-Z]/.test(s) ||
|
||||
(boardAllows(board, s) && cardShowsField(card, s)));
|
||||
return sections.filter(s => !/^scrum[A-Z]/.test(s) || boardAllows(board, s));
|
||||
}
|
||||
|
||||
Template.cardFieldSectionSort.helpers({
|
||||
@@ -939,8 +939,7 @@ Template.cardFieldSectionSort.helpers({
|
||||
return !!(board && (
|
||||
board.allowsCardSortingByNumber || board.allowsShowLists ||
|
||||
board.allowsFlowtime || board.allowsPomodoro ||
|
||||
// The card's own view already says whether Spent time is shown: with
|
||||
// hours, or ticked "On this card" to be filled in.
|
||||
// The card's view already says whether Spent time is shown.
|
||||
board.allowsSpentTime
|
||||
));
|
||||
},
|
||||
@@ -985,29 +984,35 @@ Template.cardDetails.helpers({
|
||||
// List title, Show on Card: the card's own choice, unless the
|
||||
// administrator unticked List title in Admin Panel / Settings / Visibility /
|
||||
// Features (models/lib/cardFieldVisibility.js). The card keeps its choice.
|
||||
// Its section (Card) hidden whole on Show on Card hides it as well.
|
||||
showListOnCard() {
|
||||
const board = this?.board?.();
|
||||
return Boolean(this?.showListOnCard) && !isCardFieldHiddenOnBoard(board, 'listTitle');
|
||||
const { hidesRow } = require('/models/lib/cardShownFields');
|
||||
return Boolean(this?.showListOnCard) && !isCardFieldHiddenOnBoard(board, 'listTitle')
|
||||
&& !hidesRow(board, 'card', 'listTitle');
|
||||
},
|
||||
// The header's own flags, read through the board as its cards see it
|
||||
// (cardBoardView), so a Card Settings section hidden whole on Show on Card
|
||||
// takes them away too.
|
||||
// Card color, Show on Card: the header's color, on unless turned off.
|
||||
showCardColorOnCard() {
|
||||
return Utils.getCurrentBoard()?.allowsCardColorOnCard !== false;
|
||||
return cardBoardView(this)?.allowsCardColorOnCard !== false;
|
||||
},
|
||||
// Collapse, Show on Card: the header's collapse caret, on unless turned off.
|
||||
allowsCardCollapse() {
|
||||
return Utils.getCurrentBoard()?.allowsCardCollapse !== false;
|
||||
return cardBoardView(this)?.allowsCardCollapse !== false;
|
||||
},
|
||||
// Labels title, Show on Card: the labels above the title, as on a minicard.
|
||||
showLabelsAboveTitleOnCard() {
|
||||
return Utils.getCurrentBoard()?.labelsAboveTitleOnCard === true;
|
||||
return cardBoardView(this)?.labelsAboveTitleOnCard === true;
|
||||
},
|
||||
// ...as long as the board shows labels at all.
|
||||
labelsShownAboveTitle() {
|
||||
return Utils.getCurrentBoard()?.allowsLabels !== false;
|
||||
return cardBoardView(this)?.allowsLabels !== false;
|
||||
},
|
||||
cardCollapsed() {
|
||||
// A board that turned the caret off has no collapsed cards.
|
||||
if (Utils.getCurrentBoard()?.allowsCardCollapse === false) return false;
|
||||
if (cardBoardView(this)?.allowsCardCollapse === false) return false;
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user && user.profile) {
|
||||
return !!user.profile.cardCollapsed;
|
||||
|
||||
@@ -33,6 +33,32 @@ const {
|
||||
} = require('/models/lib/cardFieldOrder');
|
||||
const { isCardFieldHiddenOnBoard } = require('/models/lib/cardFieldVisibility');
|
||||
|
||||
// The board as every minicard of it sees it (models/lib/cardShownFields.js
|
||||
// boardForMinicard): the rows of a Card Settings section hidden whole on Show
|
||||
// on Minicard read false. Every helper below that decides whether the minicard
|
||||
// draws a field reads this, not the board itself; Card Settings reads the
|
||||
// board, so its checkboxes keep showing each row's own flag.
|
||||
const { boardForMinicard, hidesRow } = require('/models/lib/cardShownFields');
|
||||
|
||||
function minicardBoardOf(data) {
|
||||
const boardId = (data && (data.boardId || (data.card && data.card.boardId))) || null;
|
||||
const board = boardId ? ReactiveCache.getBoard(boardId) : Utils.getCurrentBoard();
|
||||
return boardForMinicard(board || Utils.getCurrentBoard());
|
||||
}
|
||||
|
||||
// The minicard and its sub-templates read `currentBoard.allowsXOnMinicard`;
|
||||
// this template-level helper answers before the global one, as the opened
|
||||
// card's CARD_FIELD_TEMPLATES do (client/components/cards/cardAddFields.js).
|
||||
export const MINICARD_FIELD_TEMPLATES = Object.freeze(['minicard', 'minicardChecklist']);
|
||||
MINICARD_FIELD_TEMPLATES.forEach(name => {
|
||||
Template[name].helpers({
|
||||
currentBoard() {
|
||||
const tpl = Template.instance();
|
||||
return minicardBoardOf(tpl && tpl.data);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
function getMinicardFlag(board, onMinicardField, legacyField, defaultValue) {
|
||||
if (!board) return false;
|
||||
if (board[onMinicardField] !== null && board[onMinicardField] !== undefined) {
|
||||
@@ -61,14 +87,14 @@ Template.minicard.helpers({
|
||||
return commentBadgeTitle(this.comments(), count => TAPi18n.__('card-comments-title', count));
|
||||
},
|
||||
// #1591: the whole-minicard fold, same shape as a list's collapsed() helper.
|
||||
showCollapseControl() { return ReactiveCache.getBoard(this.boardId)?.allowsMinicardCollapse !== false; },
|
||||
showCollapseControl() { return minicardBoardOf(this)?.allowsMinicardCollapse !== false; },
|
||||
showLabelsAboveTitle() {
|
||||
const board = ReactiveCache.getBoard(this.boardId);
|
||||
const board = minicardBoardOf(this);
|
||||
return board?.labelsAboveTitleOnMinicard === true && (board.allowsMinicardCollapse === false || !Utils.getCardCollapseState(this));
|
||||
},
|
||||
labelsAboveTitle() { return ReactiveCache.getBoard(this.boardId)?.labelsAboveTitleOnMinicard === true; },
|
||||
labelsAboveTitle() { return minicardBoardOf(this)?.labelsAboveTitleOnMinicard === true; },
|
||||
minicardCollapsed() {
|
||||
return ReactiveCache.getBoard(this.boardId)?.allowsMinicardCollapse !== false && Utils.getCardCollapseState(this);
|
||||
return minicardBoardOf(this)?.allowsMinicardCollapse !== false && Utils.getCardCollapseState(this);
|
||||
},
|
||||
// The minicard's field order from Board Settings / Card's "Show on
|
||||
// Minicard" column (board.minicardFieldOrder): the sections top to bottom,
|
||||
@@ -76,19 +102,19 @@ Template.minicard.helpers({
|
||||
// `.badges` strip. A board that never set it gets the historical order.
|
||||
// models/lib/cardFieldOrder.js
|
||||
orderedMinicardSections() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return orderedMinicardSections(board?.minicardFieldOrder);
|
||||
},
|
||||
orderedMinicardDates() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return orderedMinicardFieldsOf(board?.minicardFieldOrder, 'dates');
|
||||
},
|
||||
orderedMinicardBadges() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return orderedMinicardFieldsOf(board?.minicardFieldOrder, 'badges');
|
||||
},
|
||||
showCustomFieldsOnMinicard() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return board?.allowsCustomFieldsOnMinicard === true;
|
||||
},
|
||||
// #3078: highlight the minicard when it has comments the current user has
|
||||
@@ -118,7 +144,7 @@ Template.minicard.helpers({
|
||||
const card = this;
|
||||
if (!card || !card._id) return false;
|
||||
// Unread comments, Show on Minicard: on unless turned off.
|
||||
if (Utils.getCurrentBoard()?.allowsUnreadCommentsOnMinicard === false) return false;
|
||||
if (minicardBoardOf(this)?.allowsUnreadCommentsOnMinicard === false) return false;
|
||||
const comments = ReactiveCache.getCardComments({ cardId: card._id }) || [];
|
||||
if (!comments.length) return false;
|
||||
// #6745: only this card's own last-viewed time, so opening ANOTHER card
|
||||
@@ -228,7 +254,7 @@ Template.minicard.helpers({
|
||||
|
||||
showCreatorOnMinicard() {
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret = board.allowsCreatorOnMinicard ?? false;
|
||||
@@ -240,54 +266,54 @@ Template.minicard.helpers({
|
||||
},
|
||||
|
||||
showMembers() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsMembersOnMinicard', 'allowsMembers', true);
|
||||
},
|
||||
|
||||
showAssignee() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsAssigneeOnMinicard', 'allowsAssignee', true);
|
||||
},
|
||||
showReceived() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsReceivedDateOnMinicard', 'allowsReceivedDate', true);
|
||||
},
|
||||
showStart() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsStartDateOnMinicard', 'allowsStartDate', true);
|
||||
},
|
||||
showDue() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsDueDateOnMinicard', 'allowsDueDate', true);
|
||||
},
|
||||
showEnd() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsEndDateOnMinicard', 'allowsEndDate', true);
|
||||
},
|
||||
// #2530: accumulated spent-time badge on the minicard. Defaults to true
|
||||
// (models/boards.js) since it was already shown unconditionally; this only
|
||||
// lets an admin turn it off via Card Settings.
|
||||
showSpentTime() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsSpentTimeOnMinicard', 'allowsSpentTime', true);
|
||||
},
|
||||
showLabels() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsLabelsOnMinicard', 'allowsLabels', true);
|
||||
},
|
||||
showCardNumber() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsCardNumberOnMinicard', 'allowsCardNumber', false);
|
||||
},
|
||||
// "Mark as complete" toggle on the minicard. No legacy fallback to the
|
||||
// card-details setting (allowsDueComplete): hidden by default so it only
|
||||
// appears when explicitly enabled in Card Settings > Show at Minicard.
|
||||
showDueComplete() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsDueCompleteOnMinicard', null, false);
|
||||
},
|
||||
showSubtasks() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsSubtasksOnMinicard', 'allowsSubtasks', true);
|
||||
},
|
||||
// #6688: the minicard badges that had no Board Settings / Card toggle.
|
||||
@@ -296,23 +322,23 @@ Template.minicard.helpers({
|
||||
// flag is NOT a fallback here - hiding the Dependencies section of the
|
||||
// opened card is a different decision from hiding its badge.
|
||||
showDependenciesOnMinicard() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsDependenciesOnMinicard', null, true);
|
||||
},
|
||||
showStickersOnMinicard() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsStickersOnMinicard', null, true);
|
||||
},
|
||||
showCommentCountOnMinicard() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsCommentCountOnMinicard', null, true);
|
||||
},
|
||||
showVoteOnMinicard() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsVoteOnMinicard', null, true);
|
||||
},
|
||||
showPokerOnMinicard() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return getMinicardFlag(board, 'allowsPokerOnMinicard', null, true);
|
||||
},
|
||||
// #6431: compact checklist item-count badge (finished/total) on the minicard.
|
||||
@@ -320,7 +346,7 @@ Template.minicard.helpers({
|
||||
// counting (checklistFinishedCount/checklistItemCount) is gated behind this in
|
||||
// the template, so a board with the badge off spends no resources counting.
|
||||
showChecklistCountBadge() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return !!(board && board.allowsChecklistCountBadgeOnMinicard);
|
||||
},
|
||||
// #4285: show a card's comments directly on the minicard. Opt-in and OFF by
|
||||
@@ -329,7 +355,7 @@ Template.minicard.helpers({
|
||||
// built (and the comment badge's `comments` helper already runs
|
||||
// unconditionally for the count badge) when this returns true.
|
||||
showCommentsOnMinicard() {
|
||||
const board = this.board();
|
||||
const board = minicardBoardOf(this);
|
||||
return !!(board && board.allowsCommentsOnMinicard);
|
||||
},
|
||||
// Compact, truncated preview of the most recent comments for the minicard.
|
||||
@@ -384,10 +410,10 @@ Template.minicard.helpers({
|
||||
// as it was on every board before it had a row.
|
||||
// Card color, Show on Minicard: on unless turned off.
|
||||
showCardColorOnMinicard() {
|
||||
return Utils.getCurrentBoard()?.allowsCardColorOnMinicard !== false;
|
||||
return minicardBoardOf(this)?.allowsCardColorOnMinicard !== false;
|
||||
},
|
||||
showIssueTypeOnMinicard() {
|
||||
return Utils.getCurrentBoard()?.allowsIssueTypeOnMinicard !== false;
|
||||
return minicardBoardOf(this)?.allowsIssueTypeOnMinicard !== false;
|
||||
},
|
||||
cover() {
|
||||
// #5666: for a linked card the cover lives on the real card it points at, so
|
||||
@@ -429,12 +455,14 @@ Template.minicard.helpers({
|
||||
// Show list name if either:
|
||||
// 1. Board-wide setting is enabled, OR
|
||||
// 2. This specific card has the setting enabled
|
||||
const currentBoard = this.board();
|
||||
const currentBoard = minicardBoardOf(this);
|
||||
if (!currentBoard) return false;
|
||||
if (currentBoard.allowsShowListsOnMinicard) return true;
|
||||
// The card's own List title, unless unticked in Admin Panel / Settings /
|
||||
// Visibility / Features (models/lib/cardFieldVisibility.js).
|
||||
return !isCardFieldHiddenOnBoard(currentBoard, 'listTitle') && Boolean(this.getRealCard().showListOnMinicard);
|
||||
// ...and unless its section (Card) is hidden whole on Show on Minicard.
|
||||
return !isCardFieldHiddenOnBoard(currentBoard, 'listTitle') && !hidesRow(currentBoard, 'minicard', 'listTitle')
|
||||
&& Boolean(this.getRealCard().showListOnMinicard);
|
||||
},
|
||||
|
||||
// #2426: the swimlane a card belongs to isn't otherwise visible on its
|
||||
@@ -442,7 +470,7 @@ Template.minicard.helpers({
|
||||
// swimlane), so this board-wide toggle shows the swimlane's name at the
|
||||
// bottom of the minicard, the same place/style as the list name above.
|
||||
shouldShowSwimlaneNameOnMinicard() {
|
||||
const currentBoard = this.board();
|
||||
const currentBoard = minicardBoardOf(this);
|
||||
if (!currentBoard) return false;
|
||||
return currentBoard.allowsSwimlaneNameOnMinicard === true;
|
||||
},
|
||||
@@ -455,8 +483,11 @@ Template.minicard.helpers({
|
||||
|
||||
shouldShowChecklistAtMinicard() {
|
||||
// Return checklists that should be shown on minicard
|
||||
const currentBoard = this.board();
|
||||
const currentBoard = minicardBoardOf(this);
|
||||
if (!currentBoard) return [];
|
||||
// A checklist's own "Show at minicard" overrides the board's default, so
|
||||
// the Checklists section hidden whole on Show on Minicard is asked first.
|
||||
if (hidesRow(currentBoard, 'minicard', 'checklists')) return [];
|
||||
|
||||
const checklists = this.checklists();
|
||||
const visibleChecklists = [];
|
||||
|
||||
@@ -184,23 +184,12 @@
|
||||
.card-settings-side > a.flex {
|
||||
margin: 0;
|
||||
}
|
||||
/* Select all / Select none in a section's hamburger: the Draggable table's
|
||||
buttons (boardSettingsColumnActions.css). */
|
||||
.card-settings-select {
|
||||
margin: 3px 0 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.card-settings-select button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.card-field-order-toggle,
|
||||
.card-field-order-move {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.card-field-order-move.is-disabled,
|
||||
.card-field-order-toggle.is-disabled,
|
||||
.card-always-show.is-disabled,
|
||||
.card-show-empty-fields.is-disabled,
|
||||
.card-ask-move-reason.is-disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
|
||||
@@ -269,22 +269,22 @@ template(name="boardInfoOnMyBoardsPopup")
|
||||
i.fa.fa-arrows-h
|
||||
| {{_ 'personal-list-width'}}
|
||||
|
||||
//- Board Settings / Card - what the opened card and the minicard show, and
|
||||
in what order. Opened from the board's cog menu (boardMenuPopup above).
|
||||
Whoever may not change the board sees the board's rows disabled and may
|
||||
still set their own ("Labels text", "List title"), as on the opened card.
|
||||
//- Board Settings / Card - Card Settings: what every opened card and every
|
||||
minicard of the board show, and in what order. Opened from the board's cog
|
||||
menu (boardMenuPopup above); the opened card has no Card Settings of its
|
||||
own. Whoever may not change the board sees the board's rows disabled and
|
||||
may still set their own ("Labels text").
|
||||
template(name="boardCardSettingsPopup")
|
||||
//- Board Settings / Card is the SAME template as the opened card's Card
|
||||
Settings (cardSettingsInline below), with no card: Show, then the sections
|
||||
as checklists, their rows as the items, the rest in their hamburgers
|
||||
(docs/Features/Cards/Card-Settings-On-Card.md). The popup's own header is
|
||||
its title and its close button.
|
||||
+cardSettingsInline(inPopup=true)
|
||||
//- Show, then the sections as checklists, their rows as the items, the rest
|
||||
in their hamburgers (cardSettingsInline below,
|
||||
docs/Features/Cards/Card-Settings.md). The popup's own header is its title
|
||||
and its close button.
|
||||
+cardSettingsInline
|
||||
|
||||
|
||||
//- One side's checkbox of a row of Card Settings: the board's Show on Card or
|
||||
Show on Minicard, through the handler the row names (cardSettingsRows.js).
|
||||
The same animated checkbox as On this card; only the one clicked animates.
|
||||
Only the one clicked animates.
|
||||
template(name="cardSettingsSideToggle")
|
||||
span.card-settings-side(class="card-settings-side-{{row.side}}")
|
||||
a.flex.card-field-order-toggle(class="{{#if row.writable}}{{row.toggle}}{{else}}is-disabled{{/if}} {{#if row.checked}}is-checked{{/if}} {{#if row.animating}}is-animating{{/if}}" title="{{row.title}}" role="checkbox" aria-checked="{{#if row.checked}}true{{else}}false{{/if}}")
|
||||
@@ -317,130 +317,142 @@ template(name="cardSettingsRowLabel")
|
||||
| ({{_ 'label-text-follows-board'}})
|
||||
|
||||
|
||||
//- Card Settings on the opened card (docs/Features/Cards/Card-Settings-On-Card.md).
|
||||
The card's "Card Settings" button, and everything below it, is replaced by
|
||||
this until its X closes it: the title, "Show" choosing whether the
|
||||
//- Card Settings, the body of Board Settings / Card
|
||||
(docs/Features/Cards/Card-Settings.md): "Show" choosing whether the
|
||||
checkboxes are Show on Minicard or Show on Card, then the sections as
|
||||
checklists - a title per section, its rows as the items, the checkbox the
|
||||
chosen side's board-wide setting. Sections and rows are dragged like
|
||||
checklists and their items and collapse like them; the rest of what a
|
||||
section or a row has is in its hamburger (cardSettingsSectionPopup,
|
||||
cardSettingsItemPopup). The rows, checkboxes and handlers are the popup's
|
||||
above (client/components/sidebar/sidebar.js sectionRowsOf,
|
||||
cardSettingsEvents), so the two cannot disagree. Board Settings / Card is
|
||||
this same template, in a popup (boardCardSettingsPopup above).
|
||||
checklists - a title per section with its own checkbox (the whole section
|
||||
shown on the chosen side or not), its rows as the items, the checkbox the
|
||||
chosen side's board-wide setting; a section with one row is one line.
|
||||
Sections and rows are dragged like checklists and their items and collapse
|
||||
like them; the rest of what a section or a row has is in its hamburger
|
||||
(cardSettingsSectionPopup, cardSettingsItemPopup) - drawn only when it has
|
||||
something in it. client/components/sidebar/sidebar.js inlineSectionsOf,
|
||||
cardSettingsEvents.
|
||||
template(name="cardSettingsInline")
|
||||
.card-settings-inline.js-card-settings-inline(class="{{settingsSideClass}} {{#if inPopup}}card-settings-in-popup{{/if}}")
|
||||
//- In Board Settings / Card the popup's header is the title and the X.
|
||||
unless inPopup
|
||||
.card-settings-inline-head
|
||||
h3.card-settings-inline-title {{_ 'card-settings'}}
|
||||
a.card-settings-inline-close.js-close-card-settings(href="#" role="button" title="{{_ 'close'}}" aria-label="{{_ 'close'}}")
|
||||
i.fa.fa-times(aria-hidden="true")
|
||||
//- Its own radio name: the opened card's Card Settings and Board Settings /
|
||||
Card may be open together, and one name would make them one group.
|
||||
.card-settings-inline.js-card-settings-inline
|
||||
//- The popup's header is the title and the X.
|
||||
.card-settings-inline-show(role="radiogroup" aria-label="{{_ 'card-settings-show'}}")
|
||||
span.card-settings-inline-show-label {{_ 'card-settings-show'}}
|
||||
label.card-settings-inline-show-option
|
||||
input.js-card-settings-show-side(type="radio" name="card-settings-show-side-{{#if inPopup}}popup{{else}}card{{/if}}" value="minicard" checked="{{showsSide 'minicard'}}")
|
||||
input.js-card-settings-show-side(type="radio" name="card-settings-show-side" value="minicard" checked="{{showsSide 'minicard'}}")
|
||||
span {{_ 'show-on-minicard'}}
|
||||
label.card-settings-inline-show-option
|
||||
input.js-card-settings-show-side(type="radio" name="card-settings-show-side-{{#if inPopup}}popup{{else}}card{{/if}}" value="card" checked="{{showsSide 'card'}}")
|
||||
input.js-card-settings-show-side(type="radio" name="card-settings-show-side" value="card" checked="{{showsSide 'card'}}")
|
||||
span {{_ 'show-on-card'}}
|
||||
.card-settings-inline-sections.js-card-settings-sections-sortable
|
||||
each section in inlineSections
|
||||
+cardSettingsInlineSection(section=section card=card side=showSide)
|
||||
+cardSettingsInlineSection(section=section side=showSide)
|
||||
|
||||
|
||||
//- One section of the opened card's Card Settings, drawn like a checklist: a
|
||||
title that drags and collapses it, a count of the ticked rows, and its
|
||||
hamburger; under it the rows, each a checkbox, its name and - when it has
|
||||
one - its own hamburger. Collapsed, the rows are hidden, not removed, so the
|
||||
drag bound to the list stays bound.
|
||||
//- One section of Card Settings, drawn like a checklist: a
|
||||
title that drags and collapses it, left of it a checkbox - whether the WHOLE
|
||||
section is shown on the side Card Settings shows - a count of the ticked
|
||||
rows, and its hamburger when it has anything in it; under it the rows, each
|
||||
a checkbox, its name and - when it has one - its own hamburger. Collapsed,
|
||||
the rows are hidden, not removed, so the drag bound to the list stays bound.
|
||||
A section with ONE row on this side is one line (`section.single`): one
|
||||
checkbox - the field's own, through its real checkbox kept out of sight -
|
||||
its name, the section's hamburger. Custom Fields' items are the board's
|
||||
custom fields, with a "+" under them (cardSettingsCustomFields.js).
|
||||
template(name="cardSettingsInlineSection")
|
||||
.card-settings-inline-section.js-card-settings-section(data-section="{{section.id}}" class="{{#if section.collapsed}}is-collapsed{{/if}} {{#if section.draggable}}is-draggable{{/if}}")
|
||||
.card-settings-inline-section-head
|
||||
a.card-settings-inline-collapse.js-toggle-card-settings-section(href="#" role="button" aria-expanded="{{#if section.collapsed}}false{{else}}true{{/if}}" title="{{_ 'collapse'}}" aria-label="{{_ 'collapse'}}")
|
||||
i.fa(class="{{#if section.collapsed}}fa-caret-right{{else}}fa-caret-down{{/if}}" aria-hidden="true")
|
||||
.card-settings-inline-section.js-card-settings-section(data-section="{{section.id}}" class="{{#if section.collapsed}}is-collapsed{{/if}} {{#if section.draggable}}is-draggable{{/if}} {{#if section.single}}is-single{{/if}} {{#unless section.shown}}is-section-hidden{{/unless}}")
|
||||
.card-settings-inline-section-head(class="{{#if section.flagRow}}js-card-field-order-row{{/if}}" data-key="{{#if section.flagRow}}{{section.flagRow.key}}{{/if}}" data-side="{{#if section.flagRow}}{{section.flagRow.side}}{{/if}}")
|
||||
unless section.single
|
||||
a.card-settings-inline-collapse.js-toggle-card-settings-section(href="#" role="button" aria-expanded="{{#if section.collapsed}}false{{else}}true{{/if}}" title="{{_ 'collapse'}}" aria-label="{{_ 'collapse'}}")
|
||||
i.fa(class="{{#if section.collapsed}}fa-caret-right{{else}}fa-caret-down{{/if}}" aria-hidden="true")
|
||||
if section.draggable
|
||||
if section.showDragHandles
|
||||
a.card-settings-inline-section-move.js-card-settings-section-handle(href="#" draggable="false" role="button" tabindex="0" title="{{_ 'drag-to-reorder'}}" aria-label="{{_ 'drag-to-reorder'}}")
|
||||
i.fa.fa-arrows(aria-hidden="true")
|
||||
//- The section's checkbox: for one line and for Custom Fields the
|
||||
field's own flag (and the section shown); otherwise whether the whole
|
||||
section is shown on this side. A board admin's, like the rows.
|
||||
span.card-settings-side.card-settings-section-side
|
||||
if section.flagRow
|
||||
a.flex.card-field-order-toggle.card-settings-section-toggle(class="{{#if section.flagWritable}}js-card-settings-single-toggle{{else}}is-disabled{{/if}} {{#if section.flagChecked}}is-checked{{/if}} {{#if section.flagRow.animating}}is-animating{{/if}}" data-side="{{section.side}}" title="{{section.sideTitle}}" aria-label="{{section.sideTitle}}" role="checkbox" aria-checked="{{#if section.flagChecked}}true{{else}}false{{/if}}")
|
||||
.materialCheckBox(class="{{#if section.flagChecked}}is-checked{{/if}}")
|
||||
else
|
||||
a.flex.card-field-order-toggle.card-settings-section-toggle(class="{{#if section.writable}}js-card-settings-section-shown{{else}}is-disabled{{/if}} {{#if section.shown}}is-checked{{/if}} {{#if section.animatingShown}}is-animating{{/if}}" data-side="{{section.side}}" title="{{section.sideTitle}}" aria-label="{{section.sideTitle}}" role="checkbox" aria-checked="{{#if section.shown}}true{{else}}false{{/if}}")
|
||||
.materialCheckBox(class="{{#if section.shown}}is-checked{{/if}}")
|
||||
if section.flagRow
|
||||
//- The field's real checkbox, out of sight: the line's checkbox
|
||||
clicks it, so the field is set by its own handler.
|
||||
span.card-settings-single-real.js-card-settings-single-real(hidden aria-hidden="true")
|
||||
+cardSettingsSideToggle(row=section.flagRow)
|
||||
//- Like a row: with drag handles on, only the handle drags the section.
|
||||
h4.card-settings-inline-section-title(class="{{#if section.draggable}}{{#unless section.showDragHandles}}js-card-settings-section-handle{{/unless}}{{/if}}" tabindex="{{#if section.draggable}}{{#unless section.showDragHandles}}0{{/unless}}{{/if}}" title="{{#if section.draggable}}{{#unless section.showDragHandles}}{{_ 'drag-to-reorder'}}{{/unless}}{{/if}}")
|
||||
i.fa(class=section.icon aria-hidden="true")
|
||||
| {{section.title}}
|
||||
span.card-settings-inline-section-count {{section.checkedCount}}/{{section.rows.length}}
|
||||
a.card-settings-inline-menu.js-open-card-settings-section-menu(href="#" role="button" title="{{_ 'actions'}}" aria-label="{{_ 'actions'}}")
|
||||
i.fa.fa-bars(aria-hidden="true")
|
||||
.card-settings-inline-items.js-card-field-order-sortable(data-side="{{side}}")
|
||||
each row in section.rows
|
||||
.card-settings-line.card-settings-inline-item.js-card-field-order-row(class="{{#if row.personal}}card-settings-row-personal{{/if}} {{#if row.positioned}}is-positioned{{/if}}" data-key="{{row.key}}" data-side="{{row.side}}")
|
||||
+cardSettingsSideToggle(row=row)
|
||||
+cardSettingsRowLabel(row=row)
|
||||
if row.hasMenu
|
||||
a.card-settings-inline-menu.js-open-card-settings-item-menu(href="#" role="button" title="{{_ 'actions'}}" aria-label="{{_ 'actions'}}")
|
||||
i.fa.fa-bars(aria-hidden="true")
|
||||
unless section.single
|
||||
span.card-settings-inline-section-count {{section.checkedCount}}/{{section.total}}
|
||||
if section.hasMenu
|
||||
a.card-settings-inline-menu.js-open-card-settings-section-menu(href="#" role="button" title="{{_ 'actions'}}" aria-label="{{_ 'actions'}}")
|
||||
i.fa.fa-bars(aria-hidden="true")
|
||||
unless section.single
|
||||
if section.customFields
|
||||
.card-settings-inline-items.js-card-settings-custom-fields-sortable(data-side="{{side}}")
|
||||
each field in section.customFieldItems
|
||||
.card-settings-line.card-settings-inline-item.card-settings-custom-field.js-card-settings-custom-field(class="{{#if field.draggable}}is-positioned{{/if}}" data-id="{{field.id}}" data-side="{{field.side}}")
|
||||
span.card-settings-side
|
||||
a.flex.card-field-order-toggle(class="{{#if field.writable}}js-card-settings-custom-field-toggle{{else}}is-disabled{{/if}} {{#if field.checked}}is-checked{{/if}} {{#if field.animating}}is-animating{{/if}}" title="{{field.sideTitle}}" role="checkbox" aria-checked="{{#if field.checked}}true{{else}}false{{/if}}")
|
||||
.materialCheckBox(class="{{#if field.checked}}is-checked{{/if}}")
|
||||
span.card-settings-line-label(class="{{#if field.draggable}}{{#unless field.showDragHandles}}js-card-settings-custom-field-handle card-field-order-drag-label{{/unless}}{{/if}}" tabindex="{{#if field.draggable}}{{#unless field.showDragHandles}}0{{/unless}}{{/if}}" title="{{#if field.draggable}}{{#unless field.showDragHandles}}{{_ 'drag-to-reorder'}}{{/unless}}{{/if}}")
|
||||
if field.draggable
|
||||
if field.showDragHandles
|
||||
a.flex.card-field-order-move.card-field-order-handle.js-card-settings-custom-field-handle(href="#" draggable="false" role="button" tabindex="0" title="{{_ 'drag-to-reorder'}}" aria-label="{{_ 'drag-to-reorder'}}")
|
||||
i.fa.fa-arrows
|
||||
i.fa.fa-list-alt(aria-hidden="true")
|
||||
| {{field.name}}
|
||||
if field.hasMenu
|
||||
a.card-settings-inline-menu.js-card-settings-edit-custom-field(href="#" role="button" title="{{_ 'actions'}}" aria-label="{{_ 'actions'}}")
|
||||
i.fa.fa-bars(aria-hidden="true")
|
||||
//- Under the items, also when there are none: a new custom field of
|
||||
the board, which then is the last item.
|
||||
if section.writable
|
||||
.card-settings-add-custom-field
|
||||
a.card-settings-add-custom-field-button.js-card-settings-add-custom-field(href="#" role="button" title="{{_ 'createCustomField'}}" aria-label="{{_ 'createCustomField'}}")
|
||||
i.fa.fa-plus(aria-hidden="true")
|
||||
else
|
||||
.card-settings-inline-items.js-card-field-order-sortable(data-side="{{side}}")
|
||||
each row in section.rows
|
||||
.card-settings-line.card-settings-inline-item.js-card-field-order-row(class="{{#if row.personal}}card-settings-row-personal{{/if}} {{#if row.positioned}}is-positioned{{/if}}" data-key="{{row.key}}" data-side="{{row.side}}")
|
||||
+cardSettingsSideToggle(row=row)
|
||||
+cardSettingsRowLabel(row=row)
|
||||
if row.hasMenu
|
||||
a.card-settings-inline-menu.js-open-card-settings-item-menu(href="#" role="button" title="{{_ 'actions'}}" aria-label="{{_ 'actions'}}")
|
||||
i.fa.fa-bars(aria-hidden="true")
|
||||
|
||||
|
||||
//- A section's hamburger on the opened card's Card Settings.
|
||||
//- A section's hamburger in Card Settings: the section's board actions
|
||||
(Subtask settings); and for Card, what is not a field - asking for a move
|
||||
reason and the Draggable table. A section with none of them has no
|
||||
hamburger (sidebar.js sectionHasMenu).
|
||||
template(name="cardSettingsSectionPopup")
|
||||
.card-settings-section-menu
|
||||
if sectionIsGeneral
|
||||
//- What is not a field: the popup's Card pane has these under its title.
|
||||
div.check-div.card-settings-board-option.card-settings-show-empty-fields
|
||||
a.flex.card-show-empty-fields(class="{{#if canModifyBoard}}js-show-empty-card-fields{{else}}is-disabled{{/if}} {{#if isAnimating 'showEmptyCardFields'}}is-animating{{/if}}" role="checkbox" aria-checked="{{#if showEmptyCardFields}}true{{else}}false{{/if}}")
|
||||
.materialCheckBox(class="{{#if showEmptyCardFields}}is-checked{{/if}}")
|
||||
span {{_ 'card-settings-show-empty-fields'}}
|
||||
//- What is not a field.
|
||||
div.check-div.card-settings-board-option.card-settings-ask-move-reason
|
||||
a.flex.card-ask-move-reason(class="{{#if canModifyBoard}}js-ask-move-reason{{else}}is-disabled{{/if}} {{#if isAnimating 'askForMoveReason'}}is-animating{{/if}}" role="checkbox" aria-checked="{{#if askForMoveReason}}true{{else}}false{{/if}}")
|
||||
.materialCheckBox(class="{{#if askForMoveReason}}is-checked{{/if}}")
|
||||
span {{_ 'ask-move-reason'}}
|
||||
ul.pop-over-list
|
||||
if maySelectSide
|
||||
li.card-settings-section-menu-select
|
||||
span {{sideTitle}}
|
||||
span.board-settings-column-actions.card-settings-select
|
||||
button.js-card-settings-inline-select(type="button" data-column="{{side}}" data-value="all") {{_ 'select-all'}}
|
||||
button.js-card-settings-inline-select(type="button" data-column="{{side}}" data-value="none") {{_ 'select-none'}}
|
||||
if maySelectThisCard
|
||||
li.card-settings-section-menu-select
|
||||
span {{_ 'card-settings-this-card'}}
|
||||
span.board-settings-column-actions.card-settings-select
|
||||
button.js-card-settings-inline-select(type="button" data-column="this" data-value="all") {{_ 'select-all'}}
|
||||
button.js-card-settings-inline-select(type="button" data-column="this" data-value="none") {{_ 'select-none'}}
|
||||
if maySelectAlways
|
||||
li.card-settings-section-menu-select
|
||||
span {{_ 'card-settings-show-empty'}}
|
||||
span.board-settings-column-actions.card-settings-select
|
||||
button.js-card-settings-inline-select(type="button" data-column="always" data-value="all") {{_ 'select-all'}}
|
||||
button.js-card-settings-inline-select(type="button" data-column="always" data-value="none") {{_ 'select-none'}}
|
||||
each action in sectionActions
|
||||
li
|
||||
a.js-card-settings-action(data-action="{{action.id}}")
|
||||
i.fa(class=action.icon aria-hidden="true")
|
||||
| {{action.title}}
|
||||
if sectionActions.length
|
||||
ul.pop-over-list
|
||||
each action in sectionActions
|
||||
li
|
||||
a.js-card-settings-action(data-action="{{action.id}}")
|
||||
i.fa(class=action.icon aria-hidden="true")
|
||||
| {{action.title}}
|
||||
if sectionIsGeneral
|
||||
+boardDragSettings(section="card")
|
||||
|
||||
|
||||
//- A row's hamburger on the opened card's Card Settings: whether THIS card
|
||||
shows the field, whether every card shows it empty, and Labels text's way
|
||||
back to the board's default. The cell classes are the popup's, so the
|
||||
popup's handlers set them.
|
||||
//- A row's hamburger in Card Settings: Labels text's way
|
||||
back to the board's default, while the user overrides it - the only thing a
|
||||
row's hamburger holds, so a row without it has no hamburger. The cell
|
||||
classes are the popup's, so the popup's handlers set them.
|
||||
template(name="cardSettingsItemPopup")
|
||||
with itemRow
|
||||
.card-settings-item-menu.js-card-field-order-row(data-key="{{key}}" data-side="{{side}}")
|
||||
if menu.thisCard
|
||||
div.check-div.card-settings-board-option
|
||||
a.flex.card-add-field.js-card-add-field(data-key="{{key}}" role="checkbox" aria-checked="{{#if shownOnThisCard}}true{{else}}false{{/if}}" class="{{#if isAnimating key}}is-animating{{/if}}")
|
||||
.materialCheckBox(class="{{#if shownOnThisCard}}is-checked{{/if}}")
|
||||
span {{_ 'card-settings-this-card'}}
|
||||
if menu.always
|
||||
div.check-div.card-settings-board-option
|
||||
a.flex.card-always-show.js-card-always-show(data-key="{{key}}" class="{{#if animatingAlways}}is-animating{{/if}}" role="checkbox" aria-checked="{{#if alwaysShown}}true{{else}}false{{/if}}")
|
||||
.materialCheckBox(class="{{#if alwaysShown}}is-checked{{/if}}")
|
||||
span {{_ 'card-settings-show-empty'}}
|
||||
if menu.labelTextReset
|
||||
div.check-div.card-settings-board-option
|
||||
a(class=labelTextResetClass) {{_ 'label-text-use-board-default'}}
|
||||
|
||||
@@ -23,14 +23,13 @@ const {
|
||||
const { rowsForSide, CARD_SETTINGS_ROWS } = require('/models/lib/cardSettingsRows');
|
||||
const { isRowVisible } = require('/models/lib/cardFieldVisibility');
|
||||
const cardSettingsSections = require('/models/lib/cardSettingsSections');
|
||||
const cardShownFields = require('/models/lib/cardShownFields');
|
||||
import { shownFieldsOf, closeCardSettings } from '/client/components/cards/cardAddFields';
|
||||
import { filterSubtasksOf } from '/client/lib/filterSubtasks';
|
||||
const cardSettingsCustomFields = require('/models/lib/cardSettingsCustomFields');
|
||||
import { invalidateScrumNames } from '/client/components/boards/scrum/scrumFields';
|
||||
import { InfiniteScrolling } from '/client/lib/infiniteScrolling';
|
||||
import '/client/components/boards/exportScope';
|
||||
import AccessibilitySettings from '/models/accessibilitySettings';
|
||||
import Boards from '/models/boards';
|
||||
import CustomFields from '/models/customFields';
|
||||
import CustomBoardRoles from '/models/customBoardRoles';
|
||||
const { normalizeCustomCapabilities } = require('/models/lib/boardRoleCapabilities');
|
||||
// What a custom role's description lists, in this order (#3022).
|
||||
@@ -2047,21 +2046,13 @@ function setUpCardSettings() {
|
||||
});
|
||||
}
|
||||
|
||||
// The card Card Settings is drawn for: the opened card's own Card Settings
|
||||
// passes it in (cardDetails.jade `+cardSettingsInline(card=this)`), and its
|
||||
// hamburgers pass it on. Board Settings / Card has none - it is about every
|
||||
// card of the board - so On this card is only ever on a card.
|
||||
function settingsCard() {
|
||||
const passed = (Template.currentData() || {}).card;
|
||||
return passed && passed._id ? ReactiveCache.getCard(passed._id) : null;
|
||||
}
|
||||
|
||||
// The rows of one column of Board Settings / Card, ready for the template:
|
||||
// the board's order for that side (models/lib/cardFieldOrder.js) applied to
|
||||
// the row table (models/lib/cardSettingsRows.js), each row with the checkbox
|
||||
// state its own helper reports, its icons, its translated label, and whether
|
||||
// each arrow would do anything. `data` is the popup's data context, so the
|
||||
// helpers that read it (showsListOnMinicard, settingsSideClass) see what they
|
||||
// helpers that read it (showsListOnMinicard) see what they
|
||||
// saw when the rows were written out by hand.
|
||||
function buildCardSettingsRows(side, data) {
|
||||
const boardId = Session.get('currentBoard');
|
||||
@@ -2070,11 +2061,11 @@ function buildCardSettingsRows(side, data) {
|
||||
const stored = side === 'card' ? currentBoard?.cardFieldOrder : currentBoard?.minicardFieldOrder;
|
||||
const order = applyLayoutOrder(stored, layout);
|
||||
return rowsForSide(side, order)
|
||||
// "List title" is a CARD's setting: only for somebody who may change the
|
||||
// card, the same gate the hand-written row had (`if canModifyCard`).
|
||||
// Only when the popup was opened for a card (its own menu passes it in):
|
||||
// from Board Settings there is no card for the row to change.
|
||||
.filter(row => !row[side].needsCard || (Boolean(data?.card?._id) && Utils.canModifyCard(data)))
|
||||
// "List title" is a CARD's own setting (`needsCard`): Card Settings is
|
||||
// Board Settings / Card, about every card of the board, with no card for
|
||||
// the row to change - so it is never drawn here; each card sets it in its
|
||||
// own menu (cardDetails.js js-toggle-show-list-on-minicard).
|
||||
.filter(row => !row[side].needsCard)
|
||||
// A field the administrator unticked in Admin Panel / Settings /
|
||||
// Visibility / Features is not offered on any board; the board keeps its
|
||||
// own choice for when it is ticked again. models/lib/cardFieldVisibility.js
|
||||
@@ -2120,8 +2111,6 @@ function sectionRowsOf(id, data, side, animatingKey) {
|
||||
const section = cardSettingsSections.SECTIONS.find(s => s.id === id);
|
||||
const keys = new Set(section ? section.keys : []);
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
// A linked card's data is on its source card; its own choices are its own.
|
||||
const { card: thisCard, counts } = shownFieldsOf(settingsCard());
|
||||
const writable = Boolean(board && Utils.canModifyBoard && Utils.canModifyBoard());
|
||||
const showDragHandles = Utils.showDragHandles();
|
||||
const rowOf = key => CARD_SETTINGS_ROWS.find(r => r.key === key);
|
||||
@@ -2145,26 +2134,16 @@ function sectionRowsOf(id, data, side, animatingKey) {
|
||||
labelTextOverride: built.labelTextOverride,
|
||||
labelTextOverridden: built.labelTextOverridden,
|
||||
labelTextResetClass: built.labelTextResetClass,
|
||||
perCard: side === 'card' && Boolean(thisCard) && cardShownFields.FIELD_KEYS.includes(built.key),
|
||||
shownOnThisCard: side === 'card' && Boolean(thisCard) && cardShownFields.isShown(built.key, thisCard, counts, board),
|
||||
// #6806: the board shows this field on every card, empty or not.
|
||||
alwaysShowable: side === 'card' && cardShownFields.FIELD_KEYS.includes(built.key),
|
||||
alwaysShown: cardShownFields.boardAlwaysShows(board, built.key),
|
||||
animatingAlways: animatingKey === `${built.key}:always`,
|
||||
}));
|
||||
}
|
||||
|
||||
// The card actions of section `id`: in the popup's pane when opened from a
|
||||
// card, and in that section's hamburger on the opened card's Card Settings.
|
||||
// The board actions of section `id`, in that section's hamburger in Card
|
||||
// Settings (models/lib/cardSettingsSections.js CARD_ACTIONS): for who may
|
||||
// change the board.
|
||||
function sectionCardActionsOf(id) {
|
||||
const card = settingsCard();
|
||||
const mayCard = Boolean(card && Utils.canModifyCard(card));
|
||||
const mayBoard = Boolean(Utils.canModifyBoard && Utils.canModifyBoard());
|
||||
return cardSettingsSections.cardActionsOf(id)
|
||||
// A board action for who may change the board; a card action only with
|
||||
// a card, Filter: Subtasks for any reader of it, the edits for who may
|
||||
// change it.
|
||||
.filter(action => (action.board ? mayBoard : (action.id === 'filterSubtasks' ? Boolean(card) : mayCard)))
|
||||
.filter(action => action.board && mayBoard)
|
||||
.map(action => ({
|
||||
...action,
|
||||
title: action.label.map(k => TAPi18n.__(k)).join(action.labelSeparator || ' '),
|
||||
@@ -2177,20 +2156,12 @@ const boardCardSettingsHelpers = {
|
||||
askForMoveReason() { return ReactiveCache.getBoard(Session.get('currentBoard'))?.askForMoveReason === true; },
|
||||
|
||||
isAnimating(key) { return Template.instance().animating.get() === key; },
|
||||
showEmptyCardFields() {
|
||||
return cardShownFields.boardShowsEmptyFields(ReactiveCache.getBoard(Session.get('currentBoard')));
|
||||
},
|
||||
allowsMinicardCollapse() { return ReactiveCache.getBoard(Session.get('currentBoard'))?.allowsMinicardCollapse !== false; },
|
||||
labelsAboveTitleOnMinicard() { return ReactiveCache.getBoard(Session.get('currentBoard'))?.labelsAboveTitleOnMinicard === true; },
|
||||
allowsChecklistDueDate() { return ReactiveCache.getBoard(Session.get('currentBoard'))?.allowsChecklistDueDate !== false; },
|
||||
allowsChecklistTitle() { return ReactiveCache.getBoard(Session.get('currentBoard'))?.allowsChecklistTitle !== false; },
|
||||
// The work item type badge was on every minicard before it had a row: on unless turned off.
|
||||
allowsIssueTypeOnMinicard() { return ReactiveCache.getBoard(Session.get('currentBoard'))?.allowsIssueTypeOnMinicard !== false; },
|
||||
// Show empty fields: every field is shown, so Show empty is set aside -
|
||||
// hidden from the rows' hamburgers, its ticks kept.
|
||||
settingsSideClass() {
|
||||
return cardShownFields.boardShowsEmptyFields(ReactiveCache.getBoard(Session.get('currentBoard'))) ? 'show-empty-fields' : '';
|
||||
},
|
||||
|
||||
// Board-level DEFAULT (#4256, Board Settings): whether this board shows
|
||||
// label text on its minicards unless a user overrides it. Checked means
|
||||
@@ -2220,19 +2191,6 @@ const boardCardSettingsHelpers = {
|
||||
return typeof (currentUser.profile || {}).showLabelTextOverride === 'boolean';
|
||||
},
|
||||
|
||||
// "List title" is the CARD's own setting, not the board's, so the card is
|
||||
// passed in with the side (showOnMinicardPopup) rather than looked up: a
|
||||
// minicard's menu is opened from the board, where there is no "current card".
|
||||
// Re-read from the collection so the checkbox follows its own click.
|
||||
showsListOnMinicard() {
|
||||
const card = settingsCard();
|
||||
return Boolean(card && card.showListOnMinicard);
|
||||
},
|
||||
// ...and on the opened card.
|
||||
showsListOnCard() {
|
||||
const card = settingsCard();
|
||||
return Boolean(card && card.showListOnCard);
|
||||
},
|
||||
// The labels text of the OPENED card, the user's override included.
|
||||
showsCardLabelText() {
|
||||
return resolveShowCardLabelText(ReactiveCache.getBoard(Session.get('currentBoard')));
|
||||
@@ -2679,67 +2637,11 @@ function moveCardSettingsRow(evt, direction) {
|
||||
placeInListOrder(list.dataset.side, rowEl.dataset.key, keys);
|
||||
}
|
||||
|
||||
// Select all / Select none of one column of Card Settings: the board's columns
|
||||
// for a board admin, On this card for who may change the card. `container`
|
||||
// holds the rows of the side columns (one checklist of Card Settings), each
|
||||
// set through its own checkbox's
|
||||
// handler; `keys` are the rows of On this card and Show empty. A personal
|
||||
// row (Labels text, List title) is the user's or the card's own, not the
|
||||
// board's: left as it is.
|
||||
async function selectCardSettingsColumn(tpl, container, column, on, keys) {
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
if (!container || !board) return;
|
||||
const isOn = el => el.getAttribute('aria-checked') === 'true';
|
||||
tpl.animating.set(null);
|
||||
try {
|
||||
if (column === 'this') {
|
||||
const card = settingsCard();
|
||||
if (!card || !Utils.canModifyCard(card)) return;
|
||||
const { card: view, counts } = shownFieldsOf(card);
|
||||
let next = { shownFields: card.shownFields || [], hiddenFields: card.hiddenFields || [] };
|
||||
keys.forEach(key => {
|
||||
next = cardShownFields.cardFieldsAfter({ ...view, ...next }, key, on, counts, board);
|
||||
});
|
||||
await Cards.updateAsync(card._id, { $set: next });
|
||||
return;
|
||||
}
|
||||
if (!(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
if (column === 'always') {
|
||||
await board.setCardFieldAlwaysShown(keys, on);
|
||||
return;
|
||||
}
|
||||
if (column !== 'minicard' && column !== 'card') return;
|
||||
const cells = [...container.querySelectorAll(`.js-card-field-order-row[data-side="${column}"]`)]
|
||||
.filter(cell => !cell.classList.contains('card-settings-row-personal'))
|
||||
.map(cell => cell.querySelector('.card-field-order-toggle'))
|
||||
.filter(toggle => toggle && !toggle.classList.contains('is-disabled') && isOn(toggle) !== on);
|
||||
// The Scrum rows are one write of the board's Scrum visibility: one by
|
||||
// one, each would carry the same revision and all but the first fail.
|
||||
const scrum = {};
|
||||
cells.filter(t => t.classList.contains('js-scrum-field-toggle')).forEach(toggle => {
|
||||
const key = toggle.closest('.js-card-field-order-row').dataset.key;
|
||||
const spec = CARD_SETTINGS_ROWS.find(r => r.key === key)?.[column];
|
||||
if (spec?.scrum) scrum[spec.scrum] = on;
|
||||
});
|
||||
if (Object.keys(scrum).length) {
|
||||
await Meteor.callAsync('scrum.configure', board._id, { visibility: scrum }, board.scrumRevision || 0);
|
||||
invalidateScrumNames();
|
||||
}
|
||||
// Every other row through its own checkbox's handler, which knows the
|
||||
// field it sets and its default.
|
||||
cells.filter(t => !t.classList.contains('js-scrum-field-toggle')).forEach(toggle => toggle.click());
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
tpl.animating.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
// The handlers of Card Settings: the popup Board Settings opens, and the same
|
||||
// handlers on the opened card's own Card Settings (cardSettingsInline) and its
|
||||
// hamburgers, so a checkbox does the same thing wherever it is drawn.
|
||||
const cardSettingsEvents = {
|
||||
// The same animated checkbox as Show empty fields; a board admin's.
|
||||
// The same animated checkbox as the rows; a board admin's.
|
||||
async 'click .js-ask-move-reason'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
@@ -2754,70 +2656,63 @@ const cardSettingsEvents = {
|
||||
|
||||
// A row is dragged by its handle or its name: a click on them does nothing.
|
||||
'click .js-card-field-order-handle'(evt) { evt.preventDefault(); },
|
||||
// A card action of the open section, for the card the popup was opened from.
|
||||
// A board action of the open section (CARD_ACTIONS), for a board admin.
|
||||
'click .js-card-settings-action'(evt) {
|
||||
evt.preventDefault();
|
||||
const card = settingsCard();
|
||||
const id = evt.currentTarget.dataset.action;
|
||||
const action = Object.values(cardSettingsSections.CARD_ACTIONS).flat().find(a => a.id === id);
|
||||
if (!action) return;
|
||||
if (action.board) {
|
||||
Popup.open(action.popup)(evt);
|
||||
return;
|
||||
}
|
||||
if (!card) return;
|
||||
if (id === 'filterSubtasks') {
|
||||
filterSubtasksOf(card);
|
||||
return;
|
||||
}
|
||||
if (!Utils.canModifyCard(card)) return;
|
||||
Popup.open(action.popup, { dataContext: card })(evt);
|
||||
if (!action || !action.board || !(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
Popup.open(action.popup)(evt);
|
||||
},
|
||||
// Only the checkbox just clicked animates; its own handler does the change.
|
||||
'click .card-field-order-toggle'(evt, tpl) {
|
||||
const cell = evt.currentTarget.closest('.js-card-field-order-row');
|
||||
if (cell) tpl.animating.set(`${cell.dataset.key}:${cell.dataset.side}`);
|
||||
},
|
||||
// Opened from a card: whether THIS card shows the field
|
||||
// (models/lib/cardShownFields.js) - ticked, an empty one is shown to be
|
||||
// filled in; unticked, one with data is hidden from this card.
|
||||
async 'click .js-card-add-field'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const card = settingsCard();
|
||||
const key = evt.currentTarget.dataset.key;
|
||||
if (!card || !cardShownFields.FIELD_KEYS.includes(key) || !Utils.canModifyCard(card)) return;
|
||||
tpl.animating.set(key);
|
||||
const { card: view, counts } = shownFieldsOf(card);
|
||||
const board = ReactiveCache.getBoard(card.boardId);
|
||||
const next = cardShownFields.cardFieldsAfter(view, key, !cardShownFields.isShown(key, view, counts, board), counts, board);
|
||||
await Cards.updateAsync(card._id, { $set: next });
|
||||
},
|
||||
// Card Settings / Card's "Show empty fields": every card shows all its
|
||||
// fields, the empty ones too. A board admin's, like the rest.
|
||||
async 'click .js-show-empty-card-fields'(evt, tpl) {
|
||||
// The checkbox left of a section's title: whether the whole section is
|
||||
// shown on the side Card Settings shows (models/lib/cardSettingsSections.js
|
||||
// hiddenSectionsOf). Its rows keep their own ticks. A board admin's.
|
||||
async 'click .js-card-settings-section-shown'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const sectionEl = evt.currentTarget.closest('.js-card-settings-section');
|
||||
const id = sectionEl && sectionEl.dataset.section;
|
||||
const side = evt.currentTarget.dataset.side;
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
if (!board || !(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
tpl.animating.set('showEmptyCardFields');
|
||||
if (!board || !id || !cardSettingsSections.SIDES.includes(side)) return;
|
||||
if (!(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
tpl.animating.set(`section:${id}:${side}`);
|
||||
try {
|
||||
await board.setShowEmptyCardFields(!cardShownFields.boardShowsEmptyFields(board));
|
||||
await board.setCardSettingsSectionShown(side, id, !cardSettingsSections.sectionShown(board, side, id));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
// #6806: "Show empty" - every card of the board shows the field, empty or
|
||||
// not (models/lib/cardShownFields.js). A board admin's, like the rest.
|
||||
async 'click .js-card-always-show'(evt, tpl) {
|
||||
// A section with one row on this side is one line (inlineSectionsOf
|
||||
// `single`): its one checkbox is "this field is shown on this side". It sets
|
||||
// the row's own flag through the row's own handler - the row's real
|
||||
// checkbox, kept in the line out of sight - and, turning it on, also shows
|
||||
// the section again if it was hidden whole.
|
||||
async 'click .js-card-settings-single-toggle'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const sectionEl = evt.currentTarget.closest('.js-card-settings-section');
|
||||
const real = sectionEl && sectionEl.querySelector('.js-card-settings-single-real .card-field-order-toggle');
|
||||
const id = sectionEl && sectionEl.dataset.section;
|
||||
const side = evt.currentTarget.dataset.side;
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
const key = evt.currentTarget.dataset.key;
|
||||
if (!board || !cardShownFields.FIELD_KEYS.includes(key)) return;
|
||||
if (!(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
tpl.animating.set(`${key}:always`);
|
||||
try {
|
||||
await board.setCardFieldAlwaysShown(key, !cardShownFields.boardAlwaysShows(board, key));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (!board || !real || real.classList.contains('is-disabled') || !cardSettingsSections.SIDES.includes(side)) return;
|
||||
const rowOn = real.getAttribute('aria-checked') === 'true';
|
||||
const shown = cardSettingsSections.sectionShown(board, side, id);
|
||||
if (rowOn && shown) {
|
||||
real.click();
|
||||
return;
|
||||
}
|
||||
if (!rowOn) real.click();
|
||||
if (!shown) {
|
||||
try {
|
||||
await board.setCardSettingsSectionShown(side, id, true);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
},
|
||||
// The keyboard way to drag: Up and Down on a focused handle or name move
|
||||
@@ -2888,20 +2783,6 @@ const cardSettingsEvents = {
|
||||
evt.stopPropagation();
|
||||
resetCardLabelTextOverride();
|
||||
},
|
||||
'click .js-toggle-show-list-on-card'(evt) {
|
||||
evt.preventDefault();
|
||||
const card = settingsCard();
|
||||
if (!card) return;
|
||||
Cards.update(card._id, { $set: { showListOnCard: !card.showListOnCard } });
|
||||
},
|
||||
'click .js-toggle-show-list-on-minicard'(evt) {
|
||||
evt.preventDefault();
|
||||
const card = settingsCard();
|
||||
if (!card) return;
|
||||
Cards.update(card._id, {
|
||||
$set: { showListOnMinicard: !card.showListOnMinicard },
|
||||
});
|
||||
},
|
||||
'click .js-field-has-receiveddate'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const newValue = !tpl.currentBoard.allowsReceivedDate;
|
||||
@@ -3256,16 +3137,14 @@ const cardSettingsEvents = {
|
||||
},
|
||||
};
|
||||
|
||||
// ── Card Settings on the opened card ────────────────────────────────────────
|
||||
// docs/Features/Cards/Card-Settings-On-Card.md. The opened card's "Card
|
||||
// Settings" button is replaced, with everything below it, by this: a title
|
||||
// with its X, "Show" with Show on Minicard / Show on Card, and the sections
|
||||
// as checklists - each a title with its rows as items, the checkbox the
|
||||
// chosen side's board-wide Show on Minicard or Show on Card. Sections and
|
||||
// ── Card Settings: Board Settings / Card ────────────────────────────────────
|
||||
// docs/Features/Cards/Card-Settings.md. "Show" with Show on Minicard / Show on
|
||||
// Card, and the sections as checklists - each a title with its own checkbox
|
||||
// (the whole section shown on that side) and its rows as items, the checkbox
|
||||
// the chosen side's board-wide Show on Minicard or Show on Card. Sections and
|
||||
// rows are dragged like checklists and their items, and collapse like them;
|
||||
// what else a section or a row has is in its hamburger. The rows, their
|
||||
// checkboxes and their handlers are the popup's (sectionRowsOf,
|
||||
// cardSettingsEvents), so the two cannot disagree.
|
||||
// what else a section or a row has is in its hamburger, drawn only when it has
|
||||
// something in it. The opened card has no Card Settings of its own.
|
||||
|
||||
// Where the collapsed sections are kept: the user's collapsed card sections
|
||||
// (models/users.js), under the BOARD's id, because Card Settings is the
|
||||
@@ -3278,54 +3157,138 @@ function inlineSectionCollapsed(id) {
|
||||
return Boolean(user && boardId && user.getCollapsedCardSection(boardId, inlineCollapseKey(id)) === true);
|
||||
}
|
||||
|
||||
// What a row's hamburger holds: On this card, Show empty, and the way back
|
||||
// to the board's Labels text. A row with none of them has no hamburger.
|
||||
// What a row's hamburger holds: only Labels text's way back to the board's
|
||||
// default, while the user overrides it. A row with nothing in it has no
|
||||
// hamburger at all - the icon is not drawn.
|
||||
function inlineRowMenu(row) {
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
const mayBoard = Boolean(Utils.canModifyBoard && Utils.canModifyBoard());
|
||||
return {
|
||||
thisCard: Boolean(row.perCard),
|
||||
always: Boolean(row.alwaysShowable && mayBoard && !cardShownFields.boardShowsEmptyFields(board)),
|
||||
labelTextReset: Boolean(row.labelTextOverride && row.labelTextOverridden),
|
||||
};
|
||||
}
|
||||
|
||||
// Whether a section's hamburger has anything in it: Card's always does (Ask
|
||||
// for a reason when moving cards, the Draggable table); any other section only
|
||||
// when it has card or board actions for this user here (sectionCardActionsOf).
|
||||
// Without, the icon is not drawn.
|
||||
function sectionHasMenu(section) {
|
||||
if (section && section.general) return true;
|
||||
return Boolean(section) && sectionCardActionsOf(section.id).length > 0;
|
||||
}
|
||||
|
||||
function inlineSectionsOf(tpl, data) {
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
const side = tpl.showSide.get();
|
||||
const mayBoard = Boolean(Utils.canModifyBoard && Utils.canModifyBoard());
|
||||
const showDragHandles = Utils.showDragHandles();
|
||||
const animating = tpl.animating.get();
|
||||
return cardSettingsSections.orderedSections(cardSettingsSections.SECTIONS, board && board.cardSettingsSectionOrder)
|
||||
.map(section => {
|
||||
const rows = sectionRowsOf(section.id, data, side, tpl.animating.get()).map(row => {
|
||||
const rows = sectionRowsOf(section.id, data, side, animating).map(row => {
|
||||
const menu = inlineRowMenu(row);
|
||||
// Blaze keeps a row's element by _id, so switching Show moves each
|
||||
// row to its place on the other side rather than relabelling the rows
|
||||
// where they stand - a click in between would land on another field.
|
||||
return { ...row, _id: row.key, menu, hasMenu: menu.thisCard || menu.always || menu.labelTextReset };
|
||||
return { ...row, _id: row.key, menu, hasMenu: menu.labelTextReset };
|
||||
});
|
||||
// Whether the WHOLE section is shown on this side - the checkbox left
|
||||
// of its title; its rows keep their own ticks while it is not.
|
||||
const shown = cardSettingsSections.sectionShown(board, side, section.id);
|
||||
// Custom Fields: its items are the board's custom fields, its own
|
||||
// checkbox the board's Custom Fields flag of this side - the row that
|
||||
// was its only item (models/lib/cardSettingsCustomFields.js).
|
||||
const customFields = section.id === cardSettingsCustomFields.CUSTOM_FIELDS_SECTION;
|
||||
const customFieldItems = customFields ? customFieldItemsOf(side, animating, mayBoard, showDragHandles) : [];
|
||||
// One row on this side: one line - its checkbox, its name, the
|
||||
// section's hamburger (cardSettingsSections.js isSingleRowSection).
|
||||
const single = !customFields && cardSettingsSections.isSingleRowSection(rows);
|
||||
const flagRow = single ? rows[0]
|
||||
: customFields ? rows.find(r => r.key === cardSettingsCustomFields.CUSTOM_FIELDS_ROW) || null : null;
|
||||
const items = customFields ? customFieldItems : rows;
|
||||
return {
|
||||
// Blaze keeps a section's element (and the drag bound to it) by _id.
|
||||
_id: section.id,
|
||||
// A section turning into one line (or back) is another element.
|
||||
_id: `${section.id}${single ? ':single' : ''}`,
|
||||
id: section.id,
|
||||
icon: section.icon,
|
||||
title: TAPi18n.__(section.labelKey),
|
||||
rows,
|
||||
checkedCount: rows.filter(r => r.checked).length,
|
||||
side,
|
||||
sideTitle: TAPi18n.__(side === 'minicard' ? 'show-on-minicard' : 'show-on-card'),
|
||||
rows: customFields ? [] : rows,
|
||||
shown,
|
||||
writable: mayBoard,
|
||||
animatingShown: animating === `section:${section.id}:${side}`,
|
||||
single,
|
||||
customFields,
|
||||
customFieldItems,
|
||||
// The checkbox of one line and of Custom Fields: the row's flag, and
|
||||
// the section not hidden whole - "this field is shown on this side".
|
||||
flagRow,
|
||||
flagChecked: Boolean(flagRow) && cardSettingsSections.singleLineChecked(board, side, section.id, flagRow.checked),
|
||||
flagWritable: Boolean(flagRow && flagRow.writable),
|
||||
hasMenu: sectionHasMenu(section),
|
||||
checkedCount: items.filter(r => r.checked).length,
|
||||
total: items.length,
|
||||
collapsed: inlineSectionCollapsed(section.id),
|
||||
draggable: mayBoard,
|
||||
showDragHandles,
|
||||
};
|
||||
})
|
||||
// A section with no row on this side is left out - except Card, whose
|
||||
// hamburger holds what is not a field.
|
||||
.filter(section => section.rows.length || cardSettingsSections.SECTIONS.find(s => s.id === section.id)?.general);
|
||||
// hamburger holds what is not a field, and Custom Fields while its flag
|
||||
// row is offered.
|
||||
.filter(section => section.rows.length || section.flagRow
|
||||
|| cardSettingsSections.SECTIONS.find(s => s.id === section.id)?.general);
|
||||
}
|
||||
|
||||
// The board's custom fields as Custom Fields' items in Card Settings, in their
|
||||
// `sort` order (models/lib/cardSettingsCustomFields.js): each a checkbox - its
|
||||
// Show on Card (alwaysOnCard) or Show on Minicard (showOnCard) - its name, and
|
||||
// a hamburger opening its edit form, for a board admin.
|
||||
function boardCustomFieldDefinitions() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
if (!boardId) return [];
|
||||
return cardSettingsCustomFields.orderedDefinitions(
|
||||
ReactiveCache.getCustomFields({ boardIds: { $in: [boardId] } }, { sort: { sort: 1, name: 1 } }) || []);
|
||||
}
|
||||
|
||||
function customFieldItemsOf(side, animating, mayBoard, showDragHandles) {
|
||||
const sideTitle = TAPi18n.__(side === 'minicard' ? 'show-on-minicard' : 'show-on-card');
|
||||
return boardCustomFieldDefinitions().map(definition => ({
|
||||
// Blaze keeps an item's element by _id, as it keeps the rows'.
|
||||
_id: `customField:${definition._id}`,
|
||||
id: definition._id,
|
||||
name: definition.name,
|
||||
side,
|
||||
sideTitle,
|
||||
checked: cardSettingsCustomFields.definitionChecked(definition, side),
|
||||
writable: mayBoard,
|
||||
animating: animating === `customField:${definition._id}:${side}`,
|
||||
draggable: mayBoard,
|
||||
showDragHandles,
|
||||
hasMenu: mayBoard,
|
||||
}));
|
||||
}
|
||||
|
||||
// Custom Fields' items dropped in a new order, or one moved a step by Up and
|
||||
// Down: each definition whose place changed gets its new `sort`, through the
|
||||
// same CustomFields write as the board sidebar's own list.
|
||||
function placeCustomFieldOrder(ids) {
|
||||
if (!(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
const sorts = cardSettingsCustomFields.sortsAfterDrop(boardCustomFieldDefinitions(), ids);
|
||||
Object.entries(sorts).forEach(([id, sort]) => CustomFields.update(id, { $set: { sort } }));
|
||||
}
|
||||
|
||||
// "Show": which side the checkboxes are - the opened card's when Card Settings
|
||||
// opens. A section's or a row's hamburger is a popup opened FROM Card Settings,
|
||||
// so it takes Card Settings' place and its back arrow draws Card Settings
|
||||
// again: the side is kept on Card Settings' own entry of the popup stack, so
|
||||
// coming back shows the side that was chosen, and a fresh open is Show on Card.
|
||||
const popupEntry = () => (typeof Popup !== 'undefined' && typeof Popup._getTopStack === 'function' ? Popup._getTopStack() : null);
|
||||
function setUpCardSettingsInline() {
|
||||
setUpCardSettings.call(this);
|
||||
// "Show": which side the checkboxes are - the opened card's, by default.
|
||||
this.showSide = new ReactiveVar('card');
|
||||
this.popupEntry = popupEntry();
|
||||
const kept = this.popupEntry && this.popupEntry.cardSettingsSide;
|
||||
this.showSide = new ReactiveVar(kept === 'minicard' ? 'minicard' : 'card');
|
||||
}
|
||||
|
||||
Template.cardSettingsInline.onCreated(setUpCardSettingsInline);
|
||||
@@ -3361,6 +3324,16 @@ Template.cardSettingsInline.onRendered(function () {
|
||||
// the handle with drag handles on, by the icon and name with them off
|
||||
// (cardSettingsRowLabel).
|
||||
Template.cardSettingsInlineSection.onRendered(function () {
|
||||
// Custom Fields' items reorder within Custom Fields only, as rows do.
|
||||
const fields = this.find('.js-card-settings-custom-fields-sortable');
|
||||
if (fields) {
|
||||
reorderOnDrop(this.$(fields), {
|
||||
ownListOnly: true,
|
||||
items: '> .js-card-settings-custom-field.is-positioned', handle: '.js-card-settings-custom-field-handle',
|
||||
keyOf: el => el.dataset.id,
|
||||
drop: (id, ids) => placeCustomFieldOrder(ids),
|
||||
});
|
||||
}
|
||||
const list = this.find('.js-card-field-order-sortable');
|
||||
if (!list) return;
|
||||
reorderOnDrop(this.$(list), {
|
||||
@@ -3373,13 +3346,11 @@ Template.cardSettingsInlineSection.onRendered(function () {
|
||||
|
||||
Template.cardSettingsInline.events({
|
||||
...cardSettingsEvents,
|
||||
'click .js-close-card-settings'(evt) {
|
||||
evt.preventDefault();
|
||||
closeCardSettings();
|
||||
},
|
||||
'change .js-card-settings-show-side'(evt, tpl) {
|
||||
tpl.animating.set(null);
|
||||
tpl.showSide.set(evt.currentTarget.value === 'minicard' ? 'minicard' : 'card');
|
||||
const side = evt.currentTarget.value === 'minicard' ? 'minicard' : 'card';
|
||||
tpl.showSide.set(side);
|
||||
if (tpl.popupEntry) tpl.popupEntry.cardSettingsSide = side;
|
||||
},
|
||||
async 'click .js-toggle-card-settings-section'(evt) {
|
||||
evt.preventDefault();
|
||||
@@ -3411,30 +3382,60 @@ Template.cardSettingsInline.events({
|
||||
const id = evt.currentTarget.closest('.js-card-settings-section')?.dataset.section;
|
||||
evt.preventDefault();
|
||||
if (!cardSettingsSections.SECTIONS.some(s => s.id === id)) return;
|
||||
const data = { card: settingsCard(), sectionId: id, side: tpl.showSide.get(), inPopup: Boolean(tpl.data && tpl.data.inPopup) };
|
||||
const data = { sectionId: id, side: tpl.showSide.get() };
|
||||
Popup.open('cardSettingsSection', { dataContext: data })(evt);
|
||||
},
|
||||
// Custom Fields' items: the checkbox is the definition's flag of this side.
|
||||
'click .js-card-settings-custom-field-toggle'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const item = evt.currentTarget.closest('.js-card-settings-custom-field');
|
||||
const id = item && item.dataset.id;
|
||||
const side = item && item.dataset.side;
|
||||
if (!id || !(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
// From what the checkbox shows: the cached definition can still be the
|
||||
// one before a click just made, and two quick clicks would both write on.
|
||||
const definition = ReactiveCache.getCustomField(id);
|
||||
const set = definition && cardSettingsCustomFields.definitionToggleSet(side,
|
||||
evt.currentTarget.getAttribute('aria-checked') !== 'true');
|
||||
if (!set) return;
|
||||
tpl.animating.set(`customField:${id}:${side}`);
|
||||
CustomFields.update(id, { $set: set });
|
||||
},
|
||||
// Dragged by its handle or its name: a click there does nothing.
|
||||
'click .js-card-settings-custom-field-handle'(evt) { evt.preventDefault(); },
|
||||
'keydown .js-card-settings-custom-field-handle'(evt) {
|
||||
const direction = ARROW_KEYS[evt.key];
|
||||
const item = evt.currentTarget.closest('.js-card-settings-custom-field');
|
||||
if (!direction || !item) return;
|
||||
evt.preventDefault();
|
||||
placeCustomFieldOrder(cardSettingsCustomFields.idsAfterStep(boardCustomFieldDefinitions(), item.dataset.id, direction));
|
||||
},
|
||||
// Its hamburger: the custom field's own edit form, the board sidebar's.
|
||||
'click .js-card-settings-edit-custom-field'(evt) {
|
||||
evt.preventDefault();
|
||||
const item = evt.currentTarget.closest('.js-card-settings-custom-field');
|
||||
const definition = item && ReactiveCache.getCustomField(item.dataset.id);
|
||||
if (!definition || !(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
Popup.open('editCustomField', { dataContext: definition })(evt);
|
||||
},
|
||||
// "+" under the items: a new custom field of the board, the last item.
|
||||
'click .js-card-settings-add-custom-field'(evt) {
|
||||
evt.preventDefault();
|
||||
if (!(Utils.canModifyBoard && Utils.canModifyBoard())) return;
|
||||
Popup.open('createCustomField', { dataContext: { boardId: Session.get('currentBoard') } })(evt);
|
||||
},
|
||||
'click .js-open-card-settings-item-menu'(evt, tpl) {
|
||||
const row = evt.currentTarget.closest('.js-card-field-order-row');
|
||||
const sectionEl = evt.currentTarget.closest('.js-card-settings-section');
|
||||
if (!row || !sectionEl) return;
|
||||
evt.preventDefault();
|
||||
const data = { card: settingsCard(), key: row.dataset.key, sectionId: sectionEl.dataset.section, side: tpl.showSide.get() };
|
||||
const data = { key: row.dataset.key, sectionId: sectionEl.dataset.section, side: tpl.showSide.get() };
|
||||
Popup.open('cardSettingsItem', { dataContext: data })(evt);
|
||||
},
|
||||
});
|
||||
|
||||
// A section's hamburger: Select all / Select none of the shown side, of On
|
||||
// this card and of Show empty; the section's card actions; and, for Card,
|
||||
// what is not a field - Show empty fields, asking for a move reason and the
|
||||
// Draggable table.
|
||||
// The section in the Card Settings this hamburger was opened from: the opened
|
||||
// card's and Board Settings / Card's may both be open at once.
|
||||
function inlineSectionEl(id, inPopup) {
|
||||
const which = inPopup ? '.card-settings-in-popup' : ':not(.card-settings-in-popup)';
|
||||
return document.querySelector(`.js-card-settings-inline${which} .js-card-settings-section[data-section="${id}"]`);
|
||||
}
|
||||
|
||||
// A section's hamburger: the section's card actions; and, for Card, what is
|
||||
// not a field - asking for a move reason and the Draggable table.
|
||||
Template.cardSettingsSectionPopup.onCreated(setUpCardSettings);
|
||||
Template.cardSettingsSectionPopup.helpers({
|
||||
...boardCardSettingsHelpers,
|
||||
@@ -3442,42 +3443,17 @@ Template.cardSettingsSectionPopup.helpers({
|
||||
return Boolean(cardSettingsSections.SECTIONS.find(s => s.id === this.sectionId)?.general);
|
||||
},
|
||||
sectionActions() { return sectionCardActionsOf(this.sectionId); },
|
||||
sideTitle() { return TAPi18n.__(this.side === 'minicard' ? 'show-on-minicard' : 'show-on-card'); },
|
||||
maySelectSide() { return Boolean(Utils.canModifyBoard && Utils.canModifyBoard()); },
|
||||
maySelectThisCard() {
|
||||
const card = settingsCard();
|
||||
return this.side === 'card' && Boolean(card && Utils.canModifyCard(card));
|
||||
},
|
||||
maySelectAlways() {
|
||||
const board = ReactiveCache.getBoard(Session.get('currentBoard'));
|
||||
return this.side === 'card' && Boolean(Utils.canModifyBoard && Utils.canModifyBoard())
|
||||
&& !cardShownFields.boardShowsEmptyFields(board);
|
||||
},
|
||||
});
|
||||
Template.cardSettingsSectionPopup.events({
|
||||
...cardSettingsEvents,
|
||||
async 'click .js-card-settings-inline-select'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const { column, value } = evt.currentTarget.dataset;
|
||||
const data = Template.currentData();
|
||||
const rows = sectionRowsOf(data.sectionId, data, 'card', null);
|
||||
const keys = column === 'this' ? rows.filter(r => r.perCard).map(r => r.key)
|
||||
: column === 'always' ? rows.filter(r => r.alwaysShowable).map(r => r.key) : [];
|
||||
await selectCardSettingsColumn(tpl, inlineSectionEl(data.sectionId, data.inPopup), column, value === 'all', keys);
|
||||
},
|
||||
});
|
||||
Template.cardSettingsSectionPopup.events(cardSettingsEvents);
|
||||
|
||||
// A row's hamburger: On this card, Show empty, and Labels text's way back to
|
||||
// the board's default.
|
||||
// A row's hamburger: Labels text's way back to the board's default.
|
||||
Template.cardSettingsItemPopup.onCreated(setUpCardSettings);
|
||||
Template.cardSettingsItemPopup.helpers({
|
||||
...boardCardSettingsHelpers,
|
||||
itemRow() {
|
||||
const tpl = Template.instance();
|
||||
const row = sectionRowsOf(this.sectionId, this, this.side, tpl.animating.get()).find(r => r.key === this.key);
|
||||
// `card` too: inside `with itemRow` the row is the data the shared
|
||||
// handlers read the card from (settingsCard).
|
||||
return row ? { ...row, menu: inlineRowMenu(row), card: this.card } : null;
|
||||
return row ? { ...row, menu: inlineRowMenu(row) } : null;
|
||||
},
|
||||
});
|
||||
Template.cardSettingsItemPopup.events(cardSettingsEvents);
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
const MOBILE_POPUP_MAX_WIDTH = 800;
|
||||
|
||||
// Board Settings / Card's widest; popup.css says the same
|
||||
// (`.pop-over[data-popup='boardCardSettingsPopup']`). It is the opened
|
||||
// card's Card Settings (docs/Features/Cards/Card-Settings-On-Card.md) - one
|
||||
// column of checklists - so about as wide as an opened card.
|
||||
// (`.pop-over[data-popup='boardCardSettingsPopup']`). It is Card Settings
|
||||
// (docs/Features/Cards/Card-Settings.md) - one column of checklists - so
|
||||
// about as wide as an opened card.
|
||||
const CARD_SETTINGS_MAX_WIDTH = 600;
|
||||
|
||||
function computePopupOffset(params) {
|
||||
|
||||
@@ -6,31 +6,27 @@ Description or Custom Fields and wants that section first, right under the
|
||||
card title, or wants the minicard to lead with its due date rather than its
|
||||
labels.
|
||||
|
||||
**Show on Card** says what the cards of the board CAN show. Each opened card
|
||||
then shows only the fields it has data in - plus its description, attachments
|
||||
and comments - and its own **Card Settings** button shows these same
|
||||
settings on the card itself, as checklists, with **On this card** in each
|
||||
field's hamburger ([Card Settings on the opened card](../../Cards/Card-Settings-On-Card.md)).
|
||||
|
||||
Board Settings / Card is that same Card Settings, drawn by the same
|
||||
templates, in a popup: **Show** chooses **Show on Minicard** or **Show on
|
||||
Card**, then the sections (Card, Date, Time, Members, Labels, ... Voting,
|
||||
Planning Poker, Scrum settings, Comments) are checklists - a section is a
|
||||
checklist's title, its fields the items. There is no card here, so a row's
|
||||
hamburger has no **On this card**; everything else is as on the card
|
||||
([Card Settings on the opened card](../../Cards/Card-Settings-On-Card.md)).
|
||||
This is [Card Settings](../../Cards/Card-Settings.md) - the only place it is:
|
||||
the opened card has no Card Settings of its own. **Show on Card** says what
|
||||
every opened card of the board shows - every field ticked, empty or not -
|
||||
and **Show on Minicard** what every minicard shows. **Show** chooses which,
|
||||
then the sections (Card, Date, Time, Members, Labels, ... Voting, Planning
|
||||
Poker, Scrum settings, Comments) are checklists - a section is a checklist's
|
||||
title with a checkbox of its own, its fields the items.
|
||||
|
||||
## Where to find it
|
||||
|
||||
**Board sidebar (hamburger menu) → Board Settings → Card**; on an opened
|
||||
card, its **Card Settings** button shows the same settings on the card.
|
||||
**Board sidebar (hamburger menu) → Board Settings → Card**.
|
||||
|
||||
| part | what it does |
|
||||
| --- | --- |
|
||||
| Show | which side the checkboxes and the order are: the minicard's or the opened card's |
|
||||
| checkbox | whether that side shows the field at all - the same board toggles as before (`allowsLabels`, `allowsLabelsOnMinicard`, ...) |
|
||||
| a row's hamburger | **Show empty**: every card shows the field, empty or not - by default the description, attachments and comments ([#6806](https://github.com/wekan/wekan/issues/6806)); on a card also **On this card** |
|
||||
| a section's hamburger | **Select all** / **Select none** for that section's rows; its actions (Subtask settings, Create Field, ...); for **Card** also Show empty fields, Ask for a reason when moving cards and the Draggable table |
|
||||
| a row's checkbox | whether that side shows the field at all - the same board toggles as before (`allowsLabels`, `allowsLabelsOnMinicard`, ...) |
|
||||
| a section's checkbox | whether that side shows the whole section at all (`cardSettingsHiddenOnCard`, `cardSettingsHiddenOnMinicard`); the rows keep their ticks |
|
||||
| a one-row section | one line: one checkbox - the field's own - its name, its hamburger (Subtasks, Voting, Planning Poker) |
|
||||
| Custom Fields | its items are the board's custom fields - Show on Card is *add to all cards*, Show on Minicard is *show on minicard* - dragged to reorder, **+** to create one |
|
||||
| a row's hamburger | only Labels text's way back to the board's default, while overridden; no other row has one |
|
||||
| a section's hamburger | Card: Ask for a reason when moving cards and the Draggable table; Subtasks: Subtask settings; no other section has one |
|
||||
| drag and drop | move a field earlier or later **on the chosen side only**, within its section; move a whole section above or below another |
|
||||
|
||||
What is dragged follows the member's drag handles setting: with drag handles
|
||||
@@ -39,20 +35,10 @@ the icon and name. Up and Down on a focused handle or name move it one row. A
|
||||
field cannot move to another section: dropped there, it goes back where it
|
||||
was and nothing is saved.
|
||||
|
||||
## Show empty fields
|
||||
|
||||
In Card's hamburger is **Show empty fields**, a board-wide switch, off by
|
||||
default, saved to the board (`showEmptyCardFields`):
|
||||
|
||||
- **Off** - an opened card shows the fields it has data in, plus the fields
|
||||
ticked **Show empty**.
|
||||
- **On** - every opened card shows every field ticked **Show on Card**, empty
|
||||
or not. **Show empty** then leaves the rows' hamburgers, because it has
|
||||
nothing left to decide; what was ticked is kept, and comes back into effect
|
||||
when the switch is turned off.
|
||||
|
||||
**Ask for a reason when moving cards** sits under it, as the same animated
|
||||
checkbox.
|
||||
Removed on 2026-10-28: the opened card's **Card Settings** button, **On this
|
||||
card**, **Show empty**, **Show empty fields** and the hamburgers' **Select
|
||||
all / Select none**. Every opened card shows every field its board shows,
|
||||
empty or not.
|
||||
|
||||
The minicard order and the card order are independent: a field can be third
|
||||
on the minicard and last on the card.
|
||||
@@ -60,14 +46,14 @@ on the minicard and last on the card.
|
||||
## Steps to use it
|
||||
|
||||
1. Open a board you are an admin of, click the sidebar's hamburger menu,
|
||||
then **Board Settings → Card** - or click **Card Settings** on an opened
|
||||
card, which shows the same settings on the card.
|
||||
then **Board Settings → Card**.
|
||||
2. Choose **Show on Card** or **Show on Minicard**.
|
||||
3. Drag a field within its section to move it on that side, or a section to
|
||||
move the whole section.
|
||||
4. The change takes effect immediately on every card of this board; there
|
||||
is no separate save step.
|
||||
5. Untick a checkbox to hide the field on that side; tick it to show it.
|
||||
Untick a section's checkbox to hide the whole section on that side.
|
||||
|
||||
A row that cannot move (see below) is not dragged. A dropped row goes right
|
||||
after the row now above it in the side's whole order (or right before the row
|
||||
@@ -175,13 +161,14 @@ All are on by default except the minicard's forecast.
|
||||
`applyMinicardOrder`) and the move (`moveKey`). Pure, tested without
|
||||
Meteor by `tests/cardFieldOrderLayout.test.cjs` and
|
||||
`tests/cardFieldOrder.test.cjs`.
|
||||
- `models/lib/cardShownFields.js` - which fields an opened card shows:
|
||||
`isShown()` reads the board's `cardFieldsAlwaysShown` (the Show empty
|
||||
column, written by `board.setCardFieldAlwaysShown()`) and
|
||||
`showEmptyCardFields` (`board.setShowEmptyCardFields()`). A linked card is
|
||||
decided from its source card's data. Pinned by
|
||||
`tests/cardFieldsAlwaysShown6806.test.cjs` and
|
||||
`tests/linkedCardShownFields.test.cjs`.
|
||||
- `models/lib/cardShownFields.js` - the board as its opened cards and its
|
||||
minicards see it (`boardForCard`, `boardForMinicard`): the rows of a
|
||||
section hidden on that side read false. It does not depend on the card.
|
||||
`models/lib/cardSettingsSections.js` holds the hidden-section rules
|
||||
(`hiddenSectionsOf`, `hiddenSectionsAfter`, `rowKeysHiddenBySections`),
|
||||
written through `board.setCardSettingsSectionShown(side, id, shown)`.
|
||||
Pinned by `tests/cardSettingsSectionShown.test.cjs` and
|
||||
`tests/cardShownFields.test.cjs`.
|
||||
- `models/lib/cardSettingsRows.js` - the rows of the popup: toggle class,
|
||||
board field, icons and label keys of every setting.
|
||||
- Stored on the board as `cardFieldOrder` and `minicardFieldOrder`, flat
|
||||
|
||||
@@ -1,67 +1,39 @@
|
||||
# Card fields: only what the card has, and Card Settings
|
||||
# Card fields: every field the board shows, empty or not
|
||||
|
||||
An opened card shows **only the fields it has data in**. A card with a due date
|
||||
and two labels shows its due date and its labels, and not the empty start date,
|
||||
received date, members, custom fields and the rest beside them.
|
||||
An opened card shows **every field its board shows on cards** - Board
|
||||
Settings / Card's **Show on Card** checkbox of the field's row - **empty or
|
||||
not**. An empty Due date, an empty Members, an empty Custom Fields section are
|
||||
drawn on every card of a board that shows them, ready to be filled in. A field
|
||||
the board does not show is on no card, whatever the card holds.
|
||||
|
||||
## What every card shows
|
||||
Until 2026-10-28 an opened card showed only the fields it had data in, plus
|
||||
what the board's **Show empty** column, Card's **Show empty fields** and the
|
||||
card's own **On this card** added. All three are gone, and the opened card has
|
||||
no **Card Settings** button any more: what the cards of a board show is set in
|
||||
one place, [Card Settings](Card-Settings.md) - **Board Settings / Card**.
|
||||
|
||||
By default three things are always there, empty or not, because they are what
|
||||
a card is for - and the cover when there is one:
|
||||
## What decides what a card shows
|
||||
|
||||
| Shown | When |
|
||||
| Decides | Where |
|
||||
| --- | --- |
|
||||
| **Cover** | when the card has a cover - on by default in Board Settings / Card; a new drawing becomes the cover |
|
||||
| **Description** (its title and its text) | always, also when empty |
|
||||
| **Attachments**, with **Add attachment** | always, also when there are none |
|
||||
| **Comments** | always, also when there are none |
|
||||
| Whether a field is shown on the board's cards | its row's checkbox with **Show on Card** chosen |
|
||||
| Whether a whole section (Date, Members, ...) is shown on them | the section's own checkbox, left of its title |
|
||||
| Whether the administrator offers the field at all | Admin Panel / Settings / Visibility / Features |
|
||||
|
||||
Which fields are always shown is the board's choice: Board Settings / Card's
|
||||
**Show empty** column (below). Unticked there, the description, the
|
||||
attachments and the comments are shown when they have something in them, like
|
||||
any other field.
|
||||
Two sections still appear only when there is something to show: **Similar
|
||||
cards**, when the board has cards like this one, and the **cover**, when the
|
||||
card has one (on by default in Board Settings / Card; a new drawing becomes
|
||||
the cover). **Custom Fields** is on every card the reader may change whose
|
||||
board shows it: its hamburger is where the fields are added to the card.
|
||||
|
||||
Two sections are shown only when there is something in them: **Similar
|
||||
cards**, when the board has cards like this one, and **Custom Fields**, when
|
||||
the card has a custom field value (or Custom Fields is ticked **On this card**
|
||||
in Card Settings, which is how a card with none gets the section and its menu).
|
||||
## Card Settings
|
||||
|
||||
Every other field is shown when it has data: a date that is set, labels,
|
||||
members, a checklist, a custom field with a value, a vote question, a Scrum
|
||||
sprint, and so on. A creator, a card number, the history and the other
|
||||
fields every card has anyway are shown only when added.
|
||||
|
||||
## Card Settings on the card, and Board Settings / Card
|
||||
|
||||
Under the cover, above the card's fields, the **Card Settings** button (it was
|
||||
**+ Add**) replaces itself and everything below it with Card Settings, on the
|
||||
card: its sections as checklists, their rows as checklist items, Show on
|
||||
Minicard / Show on Card choosing what the checkboxes are, and On this card and
|
||||
Show empty in each row's hamburger. That design is
|
||||
[Card Settings on the opened card](Card-Settings-On-Card.md).
|
||||
|
||||
[Board Settings / Card](../Board-Sidebar/Board-Settings/Card.md) is the same
|
||||
Card Settings, drawn by the same templates, in a popup: **Show**, then the same
|
||||
sections as checklists, the same rows and the same hamburgers. There is no
|
||||
card there, so a row's hamburger has no **On this card**, and the popup's
|
||||
header is the title and the close button.
|
||||
|
||||
- A row's **checkbox** is the board-wide Show on Card or Show on Minicard,
|
||||
whichever **Show** chooses.
|
||||
- **Show empty**, in a row's hamburger, for every per-card field: ticked,
|
||||
every card of the board shows the field, empty or not
|
||||
([#6806](https://github.com/wekan/wekan/issues/6806)). By default the
|
||||
description, attachments and comments are ticked.
|
||||
- **On this card**, in a row's hamburger on a card, says whether this card
|
||||
shows the field (the per-card fields only).
|
||||
- A section's hamburger has **Select all** and **Select none** of the chosen
|
||||
side, of On this card and of Show empty, for that section's rows - the
|
||||
board's for a board admin, On this card for who may change the card. A
|
||||
personal row (Labels text, List title) is left as it is. Card's hamburger
|
||||
also holds what is not a field: **Show empty fields**, Ask for a reason when
|
||||
moving cards and the Draggable table.
|
||||
- Sections and rows are reordered by **drag and drop**, a row only within its
|
||||
section (see [Card Settings on the opened card](Card-Settings-On-Card.md)).
|
||||
[Card Settings](Card-Settings.md) is Board Settings / Card: **Show**, then the
|
||||
sections as checklists, their rows as checklist items, Show on Minicard / Show
|
||||
on Card choosing what the checkboxes are. Each section has a checkbox of its
|
||||
own for the whole section; a section with one row is one line; Custom Fields'
|
||||
items are the board's custom fields with a **+** under them. A hamburger is
|
||||
drawn only when it has something in it.
|
||||
|
||||
A row's name leaves out what its section already says: under **Scrum settings**
|
||||
the rows are Sprint, Past sprints, Release, Issue type, Acceptance criteria and
|
||||
@@ -69,144 +41,93 @@ Backlog rank.
|
||||
|
||||
| Section | Rows |
|
||||
| --- | --- |
|
||||
| Card | Ask for a reason when moving cards, Draggable; Card number, Collapse, Parent card, Linked card, Dependencies, Card sorting by number, Show lists, List title, Swimlane, Card buttons, Similar cards |
|
||||
| Card | Ask for a reason when moving cards, Draggable (in its hamburger); Card number, Collapse, Parent card, Linked card, Dependencies, Card sorting by number, Show lists, Swimlane, Card buttons, Similar cards |
|
||||
| Date | Received, Start, Due, End, Mark as complete, Due date from the title, At risk, Forecast |
|
||||
| Time | Spent time, Flowtime, Pomodoro |
|
||||
| Members | Members, Assignee, Creator, Requested by, Assigned by, Suggested members |
|
||||
| Labels | Labels, Labels above the title, Labels text (the board's and your own), Stickers, Location, Card color |
|
||||
| Description | Description title, Description text, Description badge |
|
||||
| Checklists | Checklists, Checklist title, Checklist due date, Checklist count, Checklist from description |
|
||||
| Subtasks | Subtasks |
|
||||
| Subtasks | Subtasks (one line) |
|
||||
| Attachments | Cover image, Attachments, Attachment count, Previews, Details, Text notes, Drawing |
|
||||
| Custom Fields | Custom Fields |
|
||||
| Voting | Voting question |
|
||||
| Planning Poker | Planning Poker |
|
||||
| Custom Fields | the board's custom fields, and **+** |
|
||||
| Voting | Voting question (one line) |
|
||||
| Planning Poker | Planning Poker (one line) |
|
||||
| Scrum settings | Sprint, Past sprints, Release, Issue type, Acceptance criteria, Backlog rank |
|
||||
| Comments | Comments, Comment count, Unread comments, Activities, Action items |
|
||||
|
||||
**On this card**: ticking an empty field shows it on this card, ready to be
|
||||
filled in; unticking a field hides it from this card, also when it has data -
|
||||
the data stays, and ticking it again shows it. The choice is the card's own and
|
||||
is kept with the card; a field whose tick matches what its data would decide
|
||||
leaves nothing stored.
|
||||
|
||||
**Show empty** chooses what every card of the board shows from the start,
|
||||
ready to be filled in. A board where nearly every card gets the same fields -
|
||||
labels, a due date, a checklist - ticks those; a board that does not want an
|
||||
empty description or comments on every card unticks them, and they are shown
|
||||
when they have something in them. A card still hides an always-shown field by
|
||||
unticking **On this card**, and a field turned off in **Show on Card** stays
|
||||
off. It is the board's setting, for a board admin; with Show on Minicard
|
||||
chosen it is not in the rows' hamburgers.
|
||||
|
||||
**Show empty fields**, in Card's hamburger, is off by default.
|
||||
Ticked, every card of the board shows all its fields - the empty ones too, as
|
||||
far as Show on Card allows - and **Show empty** leaves the rows' hamburgers, because
|
||||
every field is then shown anyway. Their ticks are kept: unticked again, Show
|
||||
empty fields brings them back as they were. It is saved to the board
|
||||
(`showEmptyCardFields`), for a board admin.
|
||||
|
||||
**Card Settings** on the card is shown to whoever may change the card. Its board-wide checkboxes
|
||||
and dragging work for a board admin; for anybody else they are shown disabled,
|
||||
and only **On this card** and their own rows (Labels text, List title) change.
|
||||
Below the **Card Settings** button there is one separator line, above the first section the card
|
||||
shows: a section the card does not show draws no line of its own.
|
||||
**List title** - a card's own choice to show its list's name - is not in Card
|
||||
Settings (there is no card there); each card sets it in its own menu.
|
||||
|
||||
Board Settings / Card moves by its title bar (or the drag handle, when drag
|
||||
handles are on) and has maximize / minimize beside its close button.
|
||||
|
||||
## Card actions in their sections
|
||||
|
||||
Five actions that were in the opened card's actions menu are in the section
|
||||
they act on: in the **hamburger** at the end of that section's heading on the
|
||||
opened card, and in that section's hamburger in Card Settings.
|
||||
Actions that were in the opened card's actions menu are in the section they
|
||||
act on, in the **hamburger** at the end of that section's heading on the
|
||||
opened card:
|
||||
|
||||
| Action | Opened card | Card Settings section |
|
||||
| --- | --- | --- |
|
||||
| Filter: Subtasks | Subtasks hamburger (with the subtask settings) | Subtasks |
|
||||
| Edit voting | Voting hamburger | Voting |
|
||||
| Edit Planning Poker | Planning Poker hamburger | Planning Poker |
|
||||
| Change spent time | Spent time hamburger | Time |
|
||||
| Card kind | Scrum settings hamburger | Scrum settings |
|
||||
| Subtask settings | Subtasks hamburger | Subtasks - also from Board Settings, for a board admin |
|
||||
| Edit custom fields | Custom Fields hamburger | Custom Fields |
|
||||
| Create Field | Custom Fields hamburger, then Create Field | Custom Fields - also from Board Settings, for a board admin |
|
||||
| Link fields to another card | Custom Fields hamburger, then Link fields | Custom Fields |
|
||||
| Action | Opened card |
|
||||
| --- | --- |
|
||||
| Filter: Subtasks | Subtasks hamburger (with the subtask settings) |
|
||||
| Edit voting | Voting hamburger |
|
||||
| Edit Planning Poker | Planning Poker hamburger |
|
||||
| Change spent time | Spent time hamburger |
|
||||
| Card kind | Scrum settings hamburger |
|
||||
| Subtask settings | Subtasks hamburger - also in Card Settings' Subtasks hamburger, for a board admin |
|
||||
| Edit custom fields | Custom Fields hamburger |
|
||||
| Create Field | Custom Fields hamburger, then Create Field - also Card Settings' **+** under Custom Fields |
|
||||
| Link fields to another card | Custom Fields hamburger, then Link fields |
|
||||
|
||||
Each opens its own popup, as from the opened card. A card's action is there
|
||||
only with a card; a board's (Subtask settings, Create Field) is also in Board
|
||||
Settings / Card, for a board admin.
|
||||
Each opens its own popup. A card's own actions are on the card; Card Settings,
|
||||
which is about every card of the board, has only the board's
|
||||
(`tests/cardSectionActions.test.cjs`). Filter: Subtasks is for every reader;
|
||||
the editing actions are for whoever may change the card.
|
||||
|
||||
Everything in a section's hamburger on the opened card is also in that
|
||||
section's hamburger in Card Settings (`tests/cardSectionActions.test.cjs` fails
|
||||
for a hamburger that is not).
|
||||
## The rows that are not a field of their own
|
||||
|
||||
A section is on the opened card when the field is on in Card Settings and the
|
||||
card has data in it or shows it **On this card**: tick Voting "On this card" to
|
||||
get the Voting heading, then its hamburger asks the question. The Scrum fields
|
||||
the card shows are one section, **Scrum settings**, under one heading, each
|
||||
field by its own name. Filter: Subtasks is for every reader; the editing
|
||||
actions are for whoever may change the card.
|
||||
|
||||
## Board Settings / Card still decides what a card can show
|
||||
|
||||
**Show on Card** and Admin Panel / Settings / Visibility / Features decide what
|
||||
the cards of a board CAN show. A field turned off there is shown on no card,
|
||||
whatever the card's data or its own choice.
|
||||
|
||||
The rows that are not a field of their own - Collapse, Labels text, Labels
|
||||
above the title, the attachment previews and details, the count badges, Card
|
||||
color, Parent and Linked card, and the helpers such as Similar cards, At risk,
|
||||
Forecast and Due date from the title - change how a shown field looks or help
|
||||
to fill it. They follow Board Settings / Card alone and have no **On this
|
||||
card**.
|
||||
Collapse, Labels text, Labels above the title, the attachment previews and
|
||||
details, the count badges, Card color, Parent and Linked card, and the helpers
|
||||
such as Similar cards, At risk, Forecast and Due date from the title change how
|
||||
a shown field looks or help to fill it. They follow Board Settings / Card like
|
||||
every row.
|
||||
|
||||
## How it works
|
||||
|
||||
`models/lib/cardShownFields.js` holds the rules: what counts as data for each
|
||||
field, which fields a card shows, and the card's view of the board.
|
||||
`models/lib/cardSettingsSections.js` holds the popup's sections. The card stores two lists:
|
||||
|
||||
| Field | Holds |
|
||||
| --- | --- |
|
||||
| `shownFields` | fields shown although empty |
|
||||
| `hiddenFields` | fields hidden although they have data |
|
||||
|
||||
Only the per-card field keys are accepted (`models/cards.js`).
|
||||
|
||||
The board stores **Show empty** as `cardFieldsAlwaysShown`, a list of those
|
||||
keys (`models/boards.js`, written normalised by `setCardFieldAlwaysShown`). A
|
||||
board that never set it always shows `descriptionTitle`, `descriptionText`,
|
||||
`attachments` and `comments`; once set, the list is exactly what is ticked -
|
||||
an empty list too. A card that has made no choice of its own shows a field
|
||||
when it has data or the board always shows it.
|
||||
|
||||
The opened card's templates read the board's flags (`currentBoard.allowsDueDate`
|
||||
and so on). The opened card and each of its section templates get their own
|
||||
`currentBoard` helper (`client/components/cards/cardAddFields.js`): this card's
|
||||
view of the board, whose flags read false for the fields the card does not
|
||||
show - the same overlay as Admin Panel / Visibility / Features
|
||||
(`models/lib/cardFieldVisibility.js`), one level down. The board itself is
|
||||
never changed, and the minicard and the rest of the board are not affected.
|
||||
The Scrum fields, which are sections of their own, are left out of the card's
|
||||
`currentBoard` helper (`client/components/cards/cardAddFields.js`
|
||||
`CARD_FIELD_TEMPLATES`): the board as its cards see it
|
||||
(`models/lib/cardShownFields.js` `boardForCard`), whose flags read false for
|
||||
the rows of a section hidden whole on Show on Card - the same overlay as Admin
|
||||
Panel / Visibility / Features (`models/lib/cardFieldVisibility.js`), one level
|
||||
down. It is the same for every card of the board: it does not depend on what
|
||||
the card holds. The minicard has its own (`boardForMinicard`,
|
||||
`client/components/cards/minicard.js`). The board itself is never changed. The
|
||||
Scrum fields, which are sections of their own, are left out of the card's
|
||||
section order the same way.
|
||||
|
||||
The legacy fields - `shownFields` / `hiddenFields` on a card,
|
||||
`cardFieldsAlwaysShown` / `showEmptyCardFields` on a board - stay in the
|
||||
schema so documents that have them validate; nothing reads or writes them.
|
||||
|
||||
## Related files
|
||||
|
||||
| File | What it is |
|
||||
| --- | --- |
|
||||
| `models/lib/cardShownFields.js` | "Has data", what a card shows, the card's board view |
|
||||
| `models/lib/cardSettingsSections.js` | The popup's sections, and the row names within them |
|
||||
| `client/components/sidebar/sidebar.jade` | Card Settings (`cardSettingsInline`), and Board Settings / Card (`boardCardSettingsPopup`), which is the same template |
|
||||
| `client/components/sidebar/sidebar.js` | Its sections, the two lists, checkboxes, drag and drop and On this card |
|
||||
| `models/lib/cardShownFields.js` | The card's and the minicard's board view, `boardAllows` |
|
||||
| `models/lib/cardSettingsSections.js` | Card Settings' sections, the row names within them, which sections are hidden per side |
|
||||
| `models/lib/cardSettingsCustomFields.js` | Custom Fields' items in Card Settings |
|
||||
| `client/components/sidebar/sidebar.jade`, `sidebar.js` | Card Settings (`boardCardSettingsPopup`, `cardSettingsInline`) |
|
||||
| `client/components/sidebar/sidebar.css`, `client/components/cards/cardAddFields.css` | A row's line; the checklist look |
|
||||
| `client/components/cards/cardAddFields.js` | Card Settings opened on the card, and the card's own `currentBoard` |
|
||||
| `client/components/cards/cardDetails.jade` | The Card Settings button under the cover, the section hamburgers |
|
||||
| `client/components/cards/cardAddFields.js` | The opened card's own `currentBoard` |
|
||||
| `client/components/cards/cardDetails.jade` | The opened card, its section hamburgers |
|
||||
| `client/lib/filterSubtasks.js` | Filter: Subtasks |
|
||||
| `tests/cardSectionActions.test.cjs` | The five actions in their sections, none left in the actions menu |
|
||||
| `models/cards.js` | `shownFields`, `hiddenFields` |
|
||||
| `tests/cardShownFields.test.cjs` | The rules, the wiring, and that no card section template is left out |
|
||||
| `tests/cardFieldsAlwaysShown6806.test.cjs` | Show empty and Show empty fields: the defaults, the rule, its storage, its column, that every caller passes the board |
|
||||
| `tests/cardShownFields.test.cjs` | The rule, the wiring, and that no card section template is left out |
|
||||
| `tests/cardFieldsAlwaysShown6806.test.cjs` | #6806 met by the rule; Show empty and Show empty fields gone |
|
||||
| `tests/cardSettingsSectionShown.test.cjs` | The section checkbox, one-line sections, the views |
|
||||
| `tests/cardSectionActions.test.cjs` | The actions in their sections, none left in the actions menu |
|
||||
| `tests/cardSettingsCoverage.test.cjs` | Every row in a section, a checkbox and a handler for each side |
|
||||
| `tests/playwright/specs/card-add-fields.e2e.js` | An empty card, Card Settings on the card, a field with data, the popup |
|
||||
| `docs/Features/Cards/Card-Settings-On-Card.md` | Card Settings on the opened card |
|
||||
| `tests/playwright/specs/card-add-fields.e2e.js` | An empty card, Card Settings, the section checkbox, Custom Fields |
|
||||
| `docs/Features/Cards/Card-Settings.md` | Card Settings |
|
||||
@@ -1,110 +0,0 @@
|
||||
# Card Settings on the opened card
|
||||
|
||||
The opened card has a **Card Settings** button under its cover (it used to be
|
||||
**+ Add**). Clicking it does not open a popup: the button, and everything
|
||||
below it on the card, is **replaced** by Card Settings itself, right on the
|
||||
card. The **X** at the end of its title puts the card back.
|
||||
|
||||
**Board Settings / Card is the same Card Settings**, drawn by the same
|
||||
templates, in a popup: Show, then the same sections as checklists with the
|
||||
same rows and hamburgers. Only two things differ, because there is no card:
|
||||
the popup's own header is the title and the close button, and a row's
|
||||
hamburger has no **On this card**.
|
||||
|
||||
## Top to bottom
|
||||
|
||||
```
|
||||
Card Settings [X]
|
||||
Show ( ) Show on Minicard (•) Show on Card
|
||||
|
||||
▾ ⠿ Card 7/11 [≡]
|
||||
[x] Card number
|
||||
[ ] Collapse
|
||||
...
|
||||
▾ ⠿ Date 2/8 [≡]
|
||||
[x] Due [≡]
|
||||
[ ] Start [≡]
|
||||
...
|
||||
▸ ⠿ Time 1/3 [≡]
|
||||
...
|
||||
```
|
||||
|
||||
1. **Card Settings** - the title, with the **X** (close) at the right end of
|
||||
the title's line (the left end in a right-to-left language).
|
||||
2. **Show** and two radio buttons, **Show on Minicard** and **Show on Card**.
|
||||
They choose which side the checkboxes below are: what the board's
|
||||
minicards show, or what its opened cards show. Show on Card is chosen when
|
||||
Card Settings opens.
|
||||
3. The **sections** - Card, Date, Time, Members, Labels, Description,
|
||||
Checklists, Subtasks, Attachments, Custom Fields, Voting, Planning Poker,
|
||||
Scrum settings and Comments - drawn like the card's **checklists**:
|
||||
- the section is the **checklist's title**, with how many of its rows are
|
||||
ticked (`2/8`) and a **hamburger** menu;
|
||||
- its rows are the **checklist items**: a **checkbox**, the row's name and,
|
||||
when it has any, its own **hamburger**.
|
||||
|
||||
A section with no row on the chosen side is left out, except Card, whose
|
||||
hamburger holds what is not a field.
|
||||
|
||||
## The checkbox
|
||||
|
||||
An item's checkbox says whether that field is **visible on the chosen side**,
|
||||
for every card of the board: with **Show on Card** it is the board's Show on
|
||||
Card, with **Show on Minicard** the board's Show on Minicard. It is the same
|
||||
setting Board Settings / Card shows, so the two always agree. It is a board
|
||||
admin's: for anybody else it is shown disabled, except their own rows (Labels
|
||||
text, List title).
|
||||
|
||||
## Hamburgers
|
||||
|
||||
| Hamburger | Holds |
|
||||
| --- | --- |
|
||||
| A row's | **On this card** - whether THIS card shows the field ([Card fields](Card-Fields.md)); **Show empty** - whether every card shows it empty ([#6806](https://github.com/wekan/wekan/issues/6806)), while Show empty fields is off; Labels text's way back to the board's default. A row with none of these has no hamburger. |
|
||||
| A section's | **Select all** / **Select none** of the chosen side, of On this card and of Show empty, for that section's rows; the section's card actions (Filter: Subtasks, Edit voting, Card kind, Edit custom fields, ... - a card's own only on a card, a board's also in Board Settings); and for **Card**: Show empty fields, Ask for a reason when moving cards, and the Draggable table. |
|
||||
|
||||
On this card is for whoever may change the card; Show empty and the selects of
|
||||
the board's columns are a board admin's.
|
||||
|
||||
## Drag and drop, collapse
|
||||
|
||||
What a section or a row is dragged by follows the member's **drag handles**
|
||||
setting, as checklists do:
|
||||
|
||||
| Drag handles | Dragged by | The rest of the line |
|
||||
| --- | --- | --- |
|
||||
| On | the handle only | scrolls the page, as a touch there means to |
|
||||
| Off | the icon and name (a section: its title) | - |
|
||||
|
||||
- A **section** is dragged above or below another, as a checklist is. The
|
||||
order is the board's (`cardSettingsSectionOrder`), so every member sees the
|
||||
sections in it; a section added to WeKan later appears in its default place.
|
||||
- A **row** is dragged within its section, as a checklist item is. That moves
|
||||
the field on the chosen side: the card's order with Show on Card, the
|
||||
minicard's with Show on Minicard.
|
||||
- A row **cannot move to another section**: the sections are unrelated kinds
|
||||
of fields. Dropped on another section, it goes back where it was, and
|
||||
nothing is saved.
|
||||
- The **Up** and **Down** keys on a focused section title or row name move it
|
||||
one step.
|
||||
- Only a board admin drags.
|
||||
- The caret before a section's title **collapses** and expands it, as a
|
||||
checklist's caret does. Collapsed sections are the user's own, kept per
|
||||
board.
|
||||
|
||||
## How it works
|
||||
|
||||
| File | What it is |
|
||||
| --- | --- |
|
||||
| `client/components/cards/cardDetails.jade` | The Card Settings button; `if cardSettingsOpen` draws `+cardSettingsInline` in place of the button and everything below it |
|
||||
| `client/components/cards/cardAddFields.js` | Which card it is open on (`isCardSettingsOpen`, `closeCardSettings`), closed when the card closes |
|
||||
| `client/components/sidebar/sidebar.jade` | `cardSettingsInline`, `cardSettingsInlineSection`, `cardSettingsSectionPopup`, `cardSettingsItemPopup`; `boardCardSettingsPopup` is `+cardSettingsInline(inPopup=true)` |
|
||||
| `client/components/sidebar/sidebar.js` | The rows (`sectionRowsOf`), the handlers (`cardSettingsEvents`), Select all (`selectCardSettingsColumn`), the drags (`reorderOnDrop`, `ownListOnly` for a row) |
|
||||
| `client/components/cards/cardAddFields.css` | The checklist look |
|
||||
| `models/lib/cardSettingsSections.js` | The sections, and their order: `sectionOrder`, `orderedSections`, `sectionOrderAfterDrop` |
|
||||
| `models/boards.js` | `cardSettingsSectionOrder`, `setCardSettingsSectionOrder` |
|
||||
| `tests/cardSettingsOnCard.test.cjs` | The order rules, the layout, the shared handlers, the translations |
|
||||
| `tests/playwright/specs/card-add-fields.e2e.js` | The button, the replaced card, the checkbox, the hamburgers, the drag and collapse |
|
||||
|
||||
The card and Board Settings / Card draw the same templates with the same
|
||||
handlers, not a copy: a checkbox does the same thing wherever it is drawn, and
|
||||
a row added to Card Settings is in both.
|
||||
@@ -0,0 +1,183 @@
|
||||
# Card Settings
|
||||
|
||||
**Card Settings is Board Settings / Card**: a popup opened from the board's
|
||||
cog menu (**Board Settings → Card**). It decides what **every opened card**
|
||||
and **every minicard** of the board shows, and in what order. The opened card
|
||||
has no Card Settings of its own (until 2026-10-28 it had a **Card Settings**
|
||||
button under its cover that drew the same thing on the card; it is gone, and
|
||||
so is **On this card**).
|
||||
|
||||
An opened card shows **every field its board shows on cards**, empty or not:
|
||||
an empty Due, an empty Members, an empty Custom Fields section are drawn,
|
||||
ready to be filled in ([Card fields](Card-Fields.md)).
|
||||
|
||||
## Top to bottom
|
||||
|
||||
```
|
||||
Card Settings [□] [X] <- the popup's header
|
||||
Show ( ) Show on Minicard (•) Show on Card
|
||||
|
||||
▾ ⠿ [x] Card 7/11 [≡]
|
||||
[x] Card number
|
||||
[ ] Collapse
|
||||
...
|
||||
▾ ⠿ [x] Date 2/8
|
||||
[x] Due
|
||||
[ ] Start
|
||||
...
|
||||
▸ ⠿ [x] Time 1/3
|
||||
▾ ⠿ [x] Custom Fields 1/2
|
||||
[x] Priority [≡]
|
||||
[ ] Estimate [≡]
|
||||
[+]
|
||||
⠿ [x] Voting
|
||||
...
|
||||
```
|
||||
|
||||
1. **Show** and two radio buttons, **Show on Minicard** and **Show on Card**.
|
||||
They choose which side the checkboxes below are: what the board's
|
||||
minicards show, or what its opened cards show. Show on Card is chosen when
|
||||
Card Settings opens.
|
||||
2. The **sections** - Card, Date, Time, Members, Labels, Description,
|
||||
Checklists, Subtasks, Attachments, Custom Fields, Voting, Planning Poker,
|
||||
Scrum settings and Comments - drawn like the card's **checklists**:
|
||||
- the section is the **checklist's title**: its caret, its drag handle, a
|
||||
**checkbox** of its own, its name, how many of its rows are ticked
|
||||
(`2/8`) and - only when it has something in it - a **hamburger**;
|
||||
- its rows are the **checklist items**: a **checkbox**, the row's name and,
|
||||
when it has anything in it, its own **hamburger**.
|
||||
|
||||
A section with no row on the chosen side is left out, except Card, whose
|
||||
hamburger holds what is not a field.
|
||||
|
||||
## The checkboxes
|
||||
|
||||
**A row's checkbox** says whether that field is **visible on the chosen
|
||||
side**, for every card of the board: with **Show on Card** it is the board's
|
||||
Show on Card, with **Show on Minicard** the board's Show on Minicard.
|
||||
|
||||
**A section's checkbox**, left of its title, says whether the **whole
|
||||
section** is shown on the chosen side at all:
|
||||
|
||||
- Unticked on **Show on Card**, the section is missing from every opened card
|
||||
of the board, whatever its rows are ticked; unticked on **Show on
|
||||
Minicard**, from every minicard. The two sides are independent.
|
||||
- The rows **keep their own ticks** while their section is hidden (drawn
|
||||
faded), so ticking the section back shows exactly what was shown before.
|
||||
- The count `n/m` stays.
|
||||
|
||||
The board stores the hidden sections of each side, `cardSettingsHiddenOnCard`
|
||||
and `cardSettingsHiddenOnMinicard` (lists of section ids), written by
|
||||
`board.setCardSettingsSectionShown(side, sectionId, shown)`.
|
||||
|
||||
Every checkbox is a board admin's: for anybody else it is shown disabled,
|
||||
except their own row (Labels text).
|
||||
|
||||
## A section with one row is one line
|
||||
|
||||
A section that has exactly **one row** on the chosen side - Subtasks, Voting,
|
||||
Planning Poker - is drawn as **one line**: one checkbox, its name, and the
|
||||
section's hamburger when it has one. No caret, no count, no item under it. It
|
||||
still drags as a section.
|
||||
|
||||
Its checkbox reads **this field is shown on this side**: ticked when the
|
||||
row's own flag is on and the section is not hidden. Clicking it sets the
|
||||
row's own flag (through the row's own checkbox, kept in the line out of
|
||||
sight); turning it on also shows the section again if it was hidden whole.
|
||||
|
||||
## Custom Fields
|
||||
|
||||
Custom Fields' items are the **board's custom fields** themselves, in their
|
||||
order (`sort`, the order the card and the minicard draw them in):
|
||||
|
||||
| Show | An item's checkbox is the custom field's |
|
||||
| --- | --- |
|
||||
| Show on Minicard | **Show on minicard** (`showOnCard`, the legacy name of what the minicard reads) |
|
||||
| Show on Card | **Add to all cards** (`alwaysOnCard`): the opened card draws the custom fields the CARD carries, and this puts the field on every card of the board |
|
||||
|
||||
Unticking Show on Card stops the field being added to cards; a card that
|
||||
already carries it keeps it until it is taken off that card in its own Custom
|
||||
Fields hamburger, because a card may carry a field it was given on its own.
|
||||
|
||||
- An item's **hamburger** opens the custom field's edit form, the board
|
||||
sidebar's own.
|
||||
- Items are **dragged** within Custom Fields only - by the handle with drag
|
||||
handles on, by the icon and name with them off; Up and Down move one step.
|
||||
That writes each custom field's `sort`, so the card's and the minicard's
|
||||
order follow.
|
||||
- Under the items, also when there are none, **+** creates a custom field
|
||||
(the board's Create Field form); the new one is the last item.
|
||||
- The **section's checkbox** is the board's Custom Fields flag of the chosen
|
||||
side (`allowsCustomFields` / `allowsCustomFieldsOnMinicard`, the row that
|
||||
was its only item) and, as for a one-row section, ticking it also shows the
|
||||
section again if it was hidden whole. So there is no "Custom Fields >
|
||||
Custom Fields" line.
|
||||
|
||||
The +, the checkboxes and the hamburgers are a board admin's; anybody else
|
||||
sees no + and disabled checkboxes.
|
||||
|
||||
## Hamburgers
|
||||
|
||||
A hamburger is drawn **only when it has something in it**.
|
||||
|
||||
| Hamburger | Holds |
|
||||
| --- | --- |
|
||||
| A row's | Labels text's way back to the board's default, while the user overrides it. Every other row has none. |
|
||||
| Card's | **Ask for a reason when moving cards**, and the **Draggable** table. |
|
||||
| Subtasks' | **Subtask settings**, for a board admin. |
|
||||
| Any other section's | nothing - so no hamburger. |
|
||||
|
||||
What a card does with its own fields - Filter: Subtasks, Edit voting, Card
|
||||
kind, Edit custom fields, Link fields - is in that card's own section
|
||||
hamburgers on the opened card, not here.
|
||||
|
||||
Removed on 2026-10-28: **On this card** and **Show empty** (a row's
|
||||
hamburger), **Show empty fields** (Card's), and **Select all / Select none**
|
||||
(every section's). Empty fields are always shown, and a section has its own
|
||||
checkbox.
|
||||
|
||||
## Drag and drop, collapse
|
||||
|
||||
What a section or a row is dragged by follows the member's **drag handles**
|
||||
setting, as checklists do:
|
||||
|
||||
| Drag handles | Dragged by | The rest of the line |
|
||||
| --- | --- | --- |
|
||||
| On | the handle only | scrolls the page, as a touch there means to |
|
||||
| Off | the icon and name (a section: its title) | - |
|
||||
|
||||
- A **section** is dragged above or below another, as a checklist is. The
|
||||
order is the board's (`cardSettingsSectionOrder`), so every member sees the
|
||||
sections in it; a section added to WeKan later appears in its default place.
|
||||
- A **row** is dragged within its section, as a checklist item is. That moves
|
||||
the field on the chosen side: the card's order with Show on Card, the
|
||||
minicard's with Show on Minicard.
|
||||
- A row **cannot move to another section**: the sections are unrelated kinds
|
||||
of fields. Dropped on another section, it goes back where it was, and
|
||||
nothing is saved.
|
||||
- The **Up** and **Down** keys on a focused section title or row name move it
|
||||
one step.
|
||||
- Only a board admin drags.
|
||||
- The caret before a section's title **collapses** and expands it, as a
|
||||
checklist's caret does. Collapsed sections are the user's own, kept per
|
||||
board.
|
||||
|
||||
## How it works
|
||||
|
||||
| File | What it is |
|
||||
| --- | --- |
|
||||
| `client/components/sidebar/sidebar.jade` | `boardCardSettingsPopup` is `+cardSettingsInline`; `cardSettingsInlineSection`, `cardSettingsSectionPopup`, `cardSettingsItemPopup` |
|
||||
| `client/components/sidebar/sidebar.js` | The sections (`inlineSectionsOf`, `single`, `customFieldItems`), the rows (`sectionRowsOf`), the handlers (`cardSettingsEvents`, `js-card-settings-section-shown`, `js-card-settings-single-toggle`, the custom field ones), the drags (`reorderOnDrop`, `ownListOnly`) |
|
||||
| `client/components/cards/cardAddFields.css` | The checklist look |
|
||||
| `models/lib/cardSettingsSections.js` | The sections, their order, and whether one is shown: `hiddenSectionsOf`, `sectionShown`, `hiddenSectionsAfter`, `rowKeysHiddenBySections`, `isSingleRowSection`, `singleLineChecked` |
|
||||
| `models/lib/cardSettingsCustomFields.js` | Custom Fields' items: their order, their checkbox per side, their new `sort` after a drop |
|
||||
| `models/lib/cardShownFields.js` | `boardForCard` / `boardForMinicard`: the board as its cards / minicards see it, the rows of hidden sections reading false |
|
||||
| `client/components/cards/cardAddFields.js` | `cardBoardView`, `CARD_FIELD_TEMPLATES`: the opened card's templates read that view |
|
||||
| `client/components/cards/minicard.js` | `MINICARD_FIELD_TEMPLATES` and its helpers read the minicard's view |
|
||||
| `models/boards.js` | `cardSettingsSectionOrder`, `cardSettingsHiddenOnCard`, `cardSettingsHiddenOnMinicard`, `setCardSettingsSectionOrder`, `setCardSettingsSectionShown` |
|
||||
| `tests/cardSettingsSectionShown.test.cjs`, `tests/cardSettingsCustomFields.test.cjs`, `tests/cardSettingsOnCard.test.cjs` | The rules, the layout, the handlers |
|
||||
| `tests/playwright/specs/card-add-fields.e2e.js` | The popup, the checkboxes, the hamburgers, Custom Fields, the drag and collapse |
|
||||
|
||||
Card Settings itself reads the board as it is - its checkboxes show each
|
||||
row's own flag even while its section is hidden; only the opened card and the
|
||||
minicard read the side's view.
|
||||
@@ -1,10 +1,9 @@
|
||||
# Cards and minicards
|
||||
|
||||
Create a card in a list, then click its minicard to open its details. The
|
||||
opened card shows only the fields it has data in, plus its description,
|
||||
attachments and comments; **Card Settings** under the cover adds the rest,
|
||||
right on the card ([Card fields](Card-Fields.md),
|
||||
[Card Settings on the opened card](Card-Settings-On-Card.md)). Board-wide field visibility and order are in
|
||||
opened card shows every field its board shows on cards, empty or not
|
||||
([Card fields](Card-Fields.md)). Which fields, and in what order, on the
|
||||
opened card and on the minicard, is [Card Settings](Card-Settings.md) -
|
||||
[Board Settings / Card](../Board-Sidebar/Board-Settings/Card.md).
|
||||
|
||||
| Place or action | Guide |
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Ureueng nyang geubri buet",
|
||||
"addmore-detail": "Tamah deskripsi nyang leubeh rinci",
|
||||
"show-on-card": "Peuleumah bak Kad",
|
||||
"card-settings-this-card": "Bak kad nyoe",
|
||||
"card-settings-show-empty": "Peuleumah nyang kosong",
|
||||
"card-settings-show-empty-fields": "Peuleumah ruang nyang kosong",
|
||||
"show-on-minicard": "Peudeuh bak Minicard",
|
||||
"default-on-public-board": "Asai bak papan umum",
|
||||
"show-on-public-board": "Peuleumah bak papan umum",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Gevolmagtigde",
|
||||
"addmore-detail": "Voeg 'n meer gedetailleerde beskrywing by",
|
||||
"show-on-card": "Wys op kaart",
|
||||
"card-settings-this-card": "Op hierdie kaart",
|
||||
"card-settings-show-empty": "Wys leë",
|
||||
"card-settings-show-empty-fields": "Wys leë velde",
|
||||
"show-on-minicard": "Wys op Minicard",
|
||||
"default-on-public-board": "Verstek op openbare bord",
|
||||
"show-on-public-board": "Wys op openbare bord",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Gevolmagtigde",
|
||||
"addmore-detail": "Voeg 'n meer gedetailleerde beskrywing by",
|
||||
"show-on-card": "Wys op kaart",
|
||||
"card-settings-this-card": "Op hierdie kaart",
|
||||
"card-settings-show-empty": "Wys leë",
|
||||
"card-settings-show-empty-fields": "Wys leë velde",
|
||||
"show-on-minicard": "Wys op Minicard",
|
||||
"default-on-public-board": "Verstek op openbare bord",
|
||||
"show-on-public-board": "Wys op openbare bord",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Nea wɔde adwuma ama no",
|
||||
"addmore-detail": "Fa nkyerɛkyerɛmu a emu da hɔ kɛse ka ho",
|
||||
"show-on-card": "Kyerɛ wɔ Kaad",
|
||||
"card-settings-this-card": "Wɔ Kaad yi so",
|
||||
"card-settings-show-empty": "Kyerɛ deɛ hwee nni mu",
|
||||
"card-settings-show-empty-fields": "Kyerɛ afã a hwee nni mu",
|
||||
"show-on-minicard": "Kyerɛ wɔ Minikaad",
|
||||
"default-on-public-board": "Nea wɔahyɛ dedaw wɔ baguam bɔɔd so",
|
||||
"show-on-public-board": "Kyerɛ wɔ baguam bɔɔd so",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "ኃላፊ",
|
||||
"addmore-detail": "ይበልጥ ዝርዝር መግለጫ ጨምር",
|
||||
"show-on-card": "በካርድ ላይ አሳይ",
|
||||
"card-settings-this-card": "በዚህ ካርድ ላይ",
|
||||
"card-settings-show-empty": "ባዶዎችን አሳይ",
|
||||
"card-settings-show-empty-fields": "ባዶ መስኮችን አሳይ",
|
||||
"show-on-minicard": "በትንሽ ካርድ ላይ አሳይ",
|
||||
"default-on-public-board": "በይፋዊ ሰሌዳ ላይ ነባሪ",
|
||||
"show-on-public-board": "በይፋዊ ሰሌዳ ላይ አሳይ",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignau",
|
||||
"addmore-detail": "Adhibir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarcheta",
|
||||
"card-settings-this-card": "En esta tarcheta",
|
||||
"card-settings-show-empty": "Amostrar vuedos",
|
||||
"card-settings-show-empty-fields": "Amostrar campos vuedos",
|
||||
"show-on-minicard": "Amostrar en a minitarcheta",
|
||||
"default-on-public-board": "Predeterminau en tablero publico",
|
||||
"show-on-public-board": "Amostrar en tablero publico",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "المكلّف",
|
||||
"addmore-detail": "إضافة وصف أكثر تفصيلًا",
|
||||
"show-on-card": "عرض على البطاقة",
|
||||
"card-settings-this-card": "على هذه البطاقة",
|
||||
"card-settings-show-empty": "عرض الفارغة",
|
||||
"card-settings-show-empty-fields": "عرض الحقول الفارغة",
|
||||
"show-on-minicard": "عرض على البطاقة المصغرة",
|
||||
"default-on-public-board": "افتراضي على اللوحة العامة",
|
||||
"show-on-public-board": "إظهار على اللوحة العامة",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "المكلّف",
|
||||
"addmore-detail": "إضافة وصف أكثر تفصيلًا",
|
||||
"show-on-card": "عرض على البطاقة",
|
||||
"card-settings-this-card": "على هذه البطاقة",
|
||||
"card-settings-show-empty": "عرض الفارغة",
|
||||
"card-settings-show-empty-fields": "عرض الحقول الفارغة",
|
||||
"show-on-minicard": "عرض على البطاقة المصغرة",
|
||||
"default-on-public-board": "افتراضي على اللوحة العامة",
|
||||
"show-on-public-board": "إظهار على اللوحة العامة",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "المكلّف",
|
||||
"addmore-detail": "إضافة وصف أكثر تفصيلًا",
|
||||
"show-on-card": "عرض على البطاقة",
|
||||
"card-settings-this-card": "على هذه البطاقة",
|
||||
"card-settings-show-empty": "عرض الفارغة",
|
||||
"card-settings-show-empty-fields": "عرض الحقول الفارغة",
|
||||
"show-on-minicard": "عرض على البطاقة المصغرة",
|
||||
"default-on-public-board": "افتراضي على اللوحة العامة",
|
||||
"show-on-public-board": "إظهار على اللوحة العامة",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "محولشده",
|
||||
"addmore-detail": "افزودن توضیحات کامل تر",
|
||||
"show-on-card": "عرض على البطاقة",
|
||||
"card-settings-this-card": "على هاد البطاقة",
|
||||
"card-settings-show-empty": "عرض الخاويين",
|
||||
"card-settings-show-empty-fields": "عرض الخانات الخاوية",
|
||||
"show-on-minicard": "عرض على البطاقة المصغرة",
|
||||
"default-on-public-board": "ديفو فاللوحة العامة",
|
||||
"show-on-public-board": "بيّن فاللوحة العامة",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "দায়িত্বপ্ৰাপ্ত",
|
||||
"addmore-detail": "অধিক বিশদ বিৱৰণ যোগ কৰক",
|
||||
"show-on-card": "কাৰ্ডত দেখুৱাওক",
|
||||
"card-settings-this-card": "এই কাৰ্ডত",
|
||||
"card-settings-show-empty": "খালী দেখুৱাওক",
|
||||
"card-settings-show-empty-fields": "খালী ক্ষেত্ৰ দেখুৱাওক",
|
||||
"show-on-minicard": "মিনিকাৰ্ডত দেখুৱাওক",
|
||||
"default-on-public-board": "ৰাজহুৱা ব’ৰ্ডত অবিকল্পিত",
|
||||
"show-on-public-board": "ৰাজহুৱা ব’ৰ্ডত দেখুৱাওক",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción más detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "Nesta tarxeta",
|
||||
"card-settings-show-empty": "Amosar baleros",
|
||||
"card-settings-show-empty-fields": "Amosar campos baleros",
|
||||
"show-on-minicard": "Mostra a la Minicard",
|
||||
"default-on-public-board": "Predetermináu en tableru públicu",
|
||||
"show-on-public-board": "Amosar en tableru públicu",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Lurañataki churata",
|
||||
"addmore-detail": "yapxataña a jukʼampi detailed qhanañchäwi",
|
||||
"show-on-card": "uñachtʼayaña patana tarjeta",
|
||||
"card-settings-this-card": "Aka tarjeta patana",
|
||||
"card-settings-show-empty": "Chʼusanaka uñachtʼayaña",
|
||||
"card-settings-show-empty-fields": "Chʼusa chiqanaka uñachtʼayaña",
|
||||
"show-on-minicard": "uñachtʼayaña patana Minicard",
|
||||
"default-on-public-board": "Taqi jaqinkiri pizarranxa nayrïri",
|
||||
"show-on-public-board": "Taqi jaqinkiri pizarranxa uñachayaña",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Təyin edilmiş şəxs",
|
||||
"addmore-detail": "Daha ətraflı təsvir əlavə edin",
|
||||
"show-on-card": "Kartda göstərin",
|
||||
"card-settings-this-card": "Bu kartda",
|
||||
"card-settings-show-empty": "Boşları göstərin",
|
||||
"card-settings-show-empty-fields": "Boş sahələri göstərin",
|
||||
"show-on-minicard": "Minikartda göstərin",
|
||||
"default-on-public-board": "İctimai lövhədə standart",
|
||||
"show-on-public-board": "İctimai lövhədə göstər",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Təyin edilmiş şəxs",
|
||||
"addmore-detail": "Daha ətraflı təsvir əlavə edin",
|
||||
"show-on-card": "Kartda göstərin",
|
||||
"card-settings-this-card": "Bu kartda",
|
||||
"card-settings-show-empty": "Boşları göstərin",
|
||||
"card-settings-show-empty-fields": "Boş sahələri göstərin",
|
||||
"show-on-minicard": "Minikartda göstərin",
|
||||
"default-on-public-board": "İctimai lövhədə standart",
|
||||
"show-on-public-board": "İctimai lövhədə göstər",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Təyin edilmiş şəxs",
|
||||
"addmore-detail": "Daha ətraflı təsvir əlavə edin",
|
||||
"show-on-card": "Kartda göstərin",
|
||||
"card-settings-this-card": "Bu kartda",
|
||||
"card-settings-show-empty": "Boşları göstərin",
|
||||
"card-settings-show-empty-fields": "Boş sahələri göstərin",
|
||||
"show-on-minicard": "Minikartda göstərin",
|
||||
"default-on-public-board": "İctimai lövhədə standart",
|
||||
"show-on-public-board": "İctimai lövhədə göstər",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Яуаплы",
|
||||
"addmore-detail": "Ентеклерәк тасуирлама өҫтәргә",
|
||||
"show-on-card": "Карточкала күрһәтергә",
|
||||
"card-settings-this-card": "Был карточкала",
|
||||
"card-settings-show-empty": "Буштарын күрһәтергә",
|
||||
"card-settings-show-empty-fields": "Буш яландарҙы күрһәтергә",
|
||||
"show-on-minicard": "Мини-карточкала күрһәтергә",
|
||||
"default-on-public-board": "Асыҡ таҡтала ғәҙәттәгесә",
|
||||
"show-on-public-board": "Асыҡ таҡтала күрһәтергә",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Прызначаны",
|
||||
"addmore-detail": "Дадаць больш падрабязнае апісанне",
|
||||
"show-on-card": "Паказваць на картцы",
|
||||
"card-settings-this-card": "На гэтай картцы",
|
||||
"card-settings-show-empty": "Паказваць пустыя",
|
||||
"card-settings-show-empty-fields": "Паказваць пустыя палі",
|
||||
"show-on-minicard": "Паказваць на мінікартцы",
|
||||
"default-on-public-board": "Прадвызначана на публічнай дошцы",
|
||||
"show-on-public-board": "Паказваць на публічнай дошцы",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Изпълнител",
|
||||
"addmore-detail": "Добавяне на по-подробно описание",
|
||||
"show-on-card": "Показване на картата",
|
||||
"card-settings-this-card": "На тази карта",
|
||||
"card-settings-show-empty": "Показване на празните",
|
||||
"card-settings-show-empty-fields": "Показване на празните полета",
|
||||
"show-on-minicard": "Показване на миникартата",
|
||||
"default-on-public-board": "По подразбиране на публична дъска",
|
||||
"show-on-public-board": "Показване на публична дъска",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "जिम्मेदार",
|
||||
"addmore-detail": "अउरी विस्तार वाला विवरण जोड़ीं",
|
||||
"show-on-card": "कार्ड पर देखाईं",
|
||||
"card-settings-this-card": "एह कार्ड पर",
|
||||
"card-settings-show-empty": "खाली देखाईं",
|
||||
"card-settings-show-empty-fields": "खाली फील्ड देखाईं",
|
||||
"show-on-minicard": "छोट कार्ड पर देखाईं",
|
||||
"default-on-public-board": "सार्वजनिक बोर्ड पर डिफ़ॉल्ट",
|
||||
"show-on-public-board": "सार्वजनिक बोर्ड पर देखाईं",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Man we i gat wok",
|
||||
"addmore-detail": "Adem wan diskripsen we i gat moa ditel",
|
||||
"show-on-card": "Soemaot long Kad",
|
||||
"card-settings-this-card": "Long Kad ia",
|
||||
"card-settings-show-empty": "Soemaot ol emti",
|
||||
"card-settings-show-empty-fields": "Soemaot ol emti filed",
|
||||
"show-on-minicard": "Soemaot long Smol Kad",
|
||||
"default-on-public-board": "Difol long pablik bod",
|
||||
"show-on-public-board": "Soemaot long pablik bod",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Baarakɛla",
|
||||
"addmore-detail": "Ɲɛfɔli dafalen fara a kan",
|
||||
"show-on-card": "A jira karata kan",
|
||||
"card-settings-this-card": "Nin karata kan",
|
||||
"card-settings-show-empty": "A jira lankolonw",
|
||||
"card-settings-show-empty-fields": "A jira yɔrɔ lankolonw",
|
||||
"show-on-minicard": "A jira minikarata kan",
|
||||
"default-on-public-board": "Dabali ka tabulo bɛɛ ta la",
|
||||
"show-on-public-board": "A jira tabulo bɛɛ ta la",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "দায়িত্বপ্রাপ্ত",
|
||||
"addmore-detail": "আরও বিস্তারিত বিবরণ যোগ করুন",
|
||||
"show-on-card": "কার্ডে দেখান",
|
||||
"card-settings-this-card": "এই কার্ডে",
|
||||
"card-settings-show-empty": "খালি দেখান",
|
||||
"card-settings-show-empty-fields": "খালি ক্ষেত্রগুলি দেখান",
|
||||
"show-on-minicard": "মিনিকার্ডে দেখান",
|
||||
"default-on-public-board": "সর্বজনীন বোর্ডে ডিফল্ট",
|
||||
"show-on-public-board": "সর্বজনীন বোর্ডে দেখান",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "འགན་འཁུར་བ།",
|
||||
"addmore-detail": "ཞིབ་ཕྲའི་འགྲེལ་བཤད་ཁ་སྣོན།",
|
||||
"show-on-card": "བྱང་བུའི་སྟེང་སྟོན།",
|
||||
"card-settings-this-card": "བྱང་བུ་འདིའི་སྟེང་།",
|
||||
"card-settings-show-empty": "སྟོང་པ་སྟོན།",
|
||||
"card-settings-show-empty-fields": "ས་སྒོ་སྟོང་པ་སྟོན།",
|
||||
"show-on-minicard": "བྱང་བུ་ཆུང་ངུའི་སྟེང་སྟོན།",
|
||||
"default-on-public-board": "སྤྱི་པའི་པང་ལེབ་སྟེང་སྔོན་སྒྲིག",
|
||||
"show-on-public-board": "སྤྱི་པའི་པང་ལེབ་སྟེང་སྟོན།",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Personne assignée",
|
||||
"addmore-detail": "Ouzhpennañ un deskrivadur munutoc’h",
|
||||
"show-on-card": "Diskwel war ar gartenn",
|
||||
"card-settings-this-card": "War ar gartenn-mañ",
|
||||
"card-settings-show-empty": "Diskwel ar re c'houllo",
|
||||
"card-settings-show-empty-fields": "Diskwel ar maeziennoù goullo",
|
||||
"show-on-minicard": "Diskouez war ar gartennig",
|
||||
"default-on-public-board": "Dre ziouer war an daolenn foran",
|
||||
"show-on-public-board": "Diskouez war an daolenn foran",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Zaduženi",
|
||||
"addmore-detail": "Dodaj detaljniji opis",
|
||||
"show-on-card": "Prikaži na kartici",
|
||||
"card-settings-this-card": "Na ovoj kartici",
|
||||
"card-settings-show-empty": "Prikaži prazna",
|
||||
"card-settings-show-empty-fields": "Prikaži prazna polja",
|
||||
"show-on-minicard": "Prikaži na mini kartici",
|
||||
"default-on-public-board": "Zadano na javnoj tabli",
|
||||
"show-on-public-board": "Prikaži na javnoj tabli",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Харюусалгата",
|
||||
"addmore-detail": "Үлүү дэлгэрэнгы тайлбари нэмэхэ",
|
||||
"show-on-card": "Картада харуулха",
|
||||
"card-settings-this-card": "Энэ картада",
|
||||
"card-settings-show-empty": "Хооһониие харуулха",
|
||||
"card-settings-show-empty-fields": "Хооһон талбаринуудые харуулха",
|
||||
"show-on-minicard": "Бишыхан картада харуулха",
|
||||
"default-on-public-board": "Нээлттэ самбар дээрэ анханай",
|
||||
"show-on-public-board": "Нээлттэ самбар дээрэ харуулха",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignat",
|
||||
"addmore-detail": "Afegiu una descripció més detallada",
|
||||
"show-on-card": "Mostra a la fitxa",
|
||||
"card-settings-this-card": "En aquesta fitxa",
|
||||
"card-settings-show-empty": "Mostra els buits",
|
||||
"card-settings-show-empty-fields": "Mostra els camps buits",
|
||||
"show-on-minicard": "Mostra a la Minicard",
|
||||
"default-on-public-board": "Per defecte al tauler públic",
|
||||
"show-on-public-board": "Mostra al tauler públic",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignat",
|
||||
"addmore-detail": "Afegiu una descripció més detallada",
|
||||
"show-on-card": "Mostra a la fitxa",
|
||||
"card-settings-this-card": "En esta fitxa",
|
||||
"card-settings-show-empty": "Mostra els buits",
|
||||
"card-settings-show-empty-fields": "Mostra els camps buits",
|
||||
"show-on-minicard": "Mostra a la Minicard",
|
||||
"default-on-public-board": "Per defecte al tauler públic",
|
||||
"show-on-public-board": "Mostra al tauler públic",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignat",
|
||||
"addmore-detail": "Afegiu una descripció més detallada",
|
||||
"show-on-card": "Mostra a la fitxa",
|
||||
"card-settings-this-card": "En aquesta fitxa",
|
||||
"card-settings-show-empty": "Mostra els buits",
|
||||
"card-settings-show-empty-fields": "Mostra els camps buits",
|
||||
"show-on-minicard": "Mostra a la Minicard",
|
||||
"default-on-public-board": "Per defecte al tauler públic",
|
||||
"show-on-public-board": "Mostra al tauler públic",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "ᎠᏥᏁᏤᎸ",
|
||||
"addmore-detail": "ᎤᏟ ᎦᏅᏖᏗ ᎧᏃᎮᏓ ᎧᏁᏉᏗ",
|
||||
"show-on-card": "ᎪᏪᎵ ᎤᏍᏗ ᎠᏂ ᎠᏄᎪᏫᏍᏗ",
|
||||
"card-settings-this-card": "ᎯᎠ ᎪᏪᎵ ᎤᏍᏗ ᎠᏂ",
|
||||
"card-settings-show-empty": "ᎤᏰᎸᏒ ᎠᏄᎪᏫᏍᏗ",
|
||||
"card-settings-show-empty-fields": "ᎤᏰᎸᏒ ᏗᏟᎶᏍᏗ ᎠᏄᎪᏫᏍᏗ",
|
||||
"show-on-minicard": "ᎪᏪᎵ ᎤᏍᏗ ᎦᏴᎵ ᎠᏄᎪᏫᏍᏗ",
|
||||
"default-on-public-board": "ᏂᎦᏓ ᎤᎾᏙᏢᏒ ᎠᏂᏙᏢᏗ ᎾᎥ ᎢᏳᎵᏍᏙᏗ",
|
||||
"show-on-public-board": "ᏂᎦᏓ ᎤᎾᏙᏢᏒ ᎠᏂᏙᏢᏗ ᎾᎥ ᎬᏂᎨᏒ",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "بەرپرس",
|
||||
"addmore-detail": "وەسفێکی وردتر زیاد بکە",
|
||||
"show-on-card": "لە کارت پیشان بدە",
|
||||
"card-settings-this-card": "لەم کارتە",
|
||||
"card-settings-show-empty": "بەتاڵەکان پیشان بدە",
|
||||
"card-settings-show-empty-fields": "خانە بەتاڵەکان پیشان بدە",
|
||||
"show-on-minicard": "لە کارتی بچووک پیشان بدە",
|
||||
"default-on-public-board": "بنەڕەت لەسەر تەختەی گشتی",
|
||||
"show-on-public-board": "پیشاندان لەسەر تەختەی گشتی",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "受让人",
|
||||
"addmore-detail": "添加更详细的描述",
|
||||
"show-on-card": "显示在卡上",
|
||||
"card-settings-this-card": "在此卡上",
|
||||
"card-settings-show-empty": "显示空项",
|
||||
"card-settings-show-empty-fields": "显示空字段",
|
||||
"show-on-minicard": "显示在迷你卡上",
|
||||
"default-on-public-board": "公开看板的默认视图",
|
||||
"show-on-public-board": "在公开看板上显示",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignatu",
|
||||
"addmore-detail": "Aghjunghje una descrizzione più dettagliata",
|
||||
"show-on-card": "Mustrà nantu à a carta",
|
||||
"card-settings-this-card": "Nantu à sta carta",
|
||||
"card-settings-show-empty": "Mustrà i vioti",
|
||||
"card-settings-show-empty-fields": "Mustrà i campi vioti",
|
||||
"show-on-minicard": "Mustrà nant’à a minicarta",
|
||||
"default-on-public-board": "Predefinitu nantu à u tavulone publicu",
|
||||
"show-on-public-board": "Affissà nantu à u tavulone publicu",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Řešitel",
|
||||
"addmore-detail": "Přidat detailnější popis",
|
||||
"show-on-card": "Zobrazit na kartě",
|
||||
"card-settings-this-card": "Na této kartě",
|
||||
"card-settings-show-empty": "Zobrazit prázdné",
|
||||
"card-settings-show-empty-fields": "Zobrazit prázdná pole",
|
||||
"show-on-minicard": "Zobrazit na minikartě",
|
||||
"default-on-public-board": "Výchozí na veřejné tabuli",
|
||||
"show-on-public-board": "Zobrazit na veřejné tabuli",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Řešitel",
|
||||
"addmore-detail": "Přidat detailnější popis",
|
||||
"show-on-card": "Zobrazit na kartě",
|
||||
"card-settings-this-card": "Na této kartě",
|
||||
"card-settings-show-empty": "Zobrazit prázdné",
|
||||
"card-settings-show-empty-fields": "Zobrazit prázdná pole",
|
||||
"show-on-minicard": "Zobrazit na minikartě",
|
||||
"default-on-public-board": "Výchozí na veřejné tabuli",
|
||||
"show-on-public-board": "Zobrazit na veřejné tabuli",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Òdpòwiedzalny",
|
||||
"addmore-detail": "Dodôj bardziej szczegòłowi òpisënk",
|
||||
"show-on-card": "Pòkôżë na kôrce",
|
||||
"card-settings-this-card": "Na ti kôrce",
|
||||
"card-settings-show-empty": "Pòkôżë pùsté",
|
||||
"card-settings-show-empty-fields": "Pòkôżë pùsté pòla",
|
||||
"show-on-minicard": "Wyświetl na miniaturze kôrtë",
|
||||
"default-on-public-board": "Domëslno na pùbliczny tôflë",
|
||||
"show-on-public-board": "Pòkôżë na pùbliczny tôflë",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Яваплӑ",
|
||||
"addmore-detail": "Туллин ӑнлантару хушас",
|
||||
"show-on-card": "Карточка ҫинче кӑтартас",
|
||||
"card-settings-this-card": "Ҫак карточка ҫинче",
|
||||
"card-settings-show-empty": "Пушӑсене кӑтартас",
|
||||
"card-settings-show-empty-fields": "Пушӑ уйсене кӑтартас",
|
||||
"show-on-minicard": "Кӗске карточка ҫинче кӑтартас",
|
||||
"default-on-public-board": "Уҫӑ хӑма ҫинче тӗп",
|
||||
"show-on-public-board": "Уҫӑ хӑма ҫинче кӑтарт",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Aseinai",
|
||||
"addmore-detail": "Ychwanegu disgrifiad manylach",
|
||||
"show-on-card": "Dangos ar Gerdyn",
|
||||
"card-settings-this-card": "Ar y Cerdyn hwn",
|
||||
"card-settings-show-empty": "Dangos rhai gwag",
|
||||
"card-settings-show-empty-fields": "Dangos meysydd gwag",
|
||||
"show-on-minicard": "Dangoswch ar Gerdyn Mini",
|
||||
"default-on-public-board": "Rhagosodiad ar fwrdd cyhoeddus",
|
||||
"show-on-public-board": "Dangos ar fwrdd cyhoeddus",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Aseinai",
|
||||
"addmore-detail": "Ychwanegu disgrifiad manylach",
|
||||
"show-on-card": "Dangos ar Gerdyn",
|
||||
"card-settings-this-card": "Ar y Cerdyn hwn",
|
||||
"card-settings-show-empty": "Dangos rhai gwag",
|
||||
"card-settings-show-empty-fields": "Dangos meysydd gwag",
|
||||
"show-on-minicard": "Dangoswch ar Gerdyn Mini",
|
||||
"default-on-public-board": "Rhagosodiad ar fwrdd cyhoeddus",
|
||||
"show-on-public-board": "Dangos ar fwrdd cyhoeddus",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Tildelt til",
|
||||
"addmore-detail": "Tilføj en mere detaljeret beskrivelse",
|
||||
"show-on-card": "Vis på kort",
|
||||
"card-settings-this-card": "På dette kort",
|
||||
"card-settings-show-empty": "Vis tomme",
|
||||
"card-settings-show-empty-fields": "Vis tomme felter",
|
||||
"show-on-minicard": "Vis på minikort",
|
||||
"default-on-public-board": "Standard på offentlig tavle",
|
||||
"show-on-public-board": "Vis på offentlig tavle",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Zugewiesen",
|
||||
"addmore-detail": "Eine detailliertere Beschreibung hinzufügen",
|
||||
"show-on-card": "Zeige auf Karte",
|
||||
"card-settings-this-card": "Auf dieser Karte",
|
||||
"card-settings-show-empty": "Zeige leere",
|
||||
"card-settings-show-empty-fields": "Zeige leere Felder",
|
||||
"show-on-minicard": "Zeige auf Minikarte",
|
||||
"default-on-public-board": "Standard auf öffentlicher Arbeitstafel",
|
||||
"show-on-public-board": "Zeige auf öffentlicher Arbeitstafel",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Zugewiesen",
|
||||
"addmore-detail": "Eine detailliertere Beschreibung hinzufügen",
|
||||
"show-on-card": "Zeige auf Karte",
|
||||
"card-settings-this-card": "Auf dieser Karte",
|
||||
"card-settings-show-empty": "Zeige leere",
|
||||
"card-settings-show-empty-fields": "Zeige leere Felder",
|
||||
"show-on-minicard": "Anzeigen auf Minikarte",
|
||||
"default-on-public-board": "Standard auf öffentlicher Arbeitstafel",
|
||||
"show-on-public-board": "Zeige auf öffentlicher Arbeitstafel",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Zugewiesen",
|
||||
"addmore-detail": "Eine detailliertere Beschreibung hinzufügen",
|
||||
"show-on-card": "Zeige auf Karte",
|
||||
"card-settings-this-card": "Auf dieser Karte",
|
||||
"card-settings-show-empty": "Zeige leere",
|
||||
"card-settings-show-empty-fields": "Zeige leere Felder",
|
||||
"show-on-minicard": "Zeige auf Minikarte",
|
||||
"default-on-public-board": "Standard auf öffentlicher Arbeitstafel",
|
||||
"show-on-public-board": "Zeige auf öffentlicher Arbeitstafel",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Zugewiesen",
|
||||
"addmore-detail": "Eine detailliertere Beschreibung hinzufügen",
|
||||
"show-on-card": "Zeige auf Karte",
|
||||
"card-settings-this-card": "Auf dieser Karte",
|
||||
"card-settings-show-empty": "Zeige leere",
|
||||
"card-settings-show-empty-fields": "Zeige leere Felder",
|
||||
"show-on-minicard": "Zeige auf Minikarte",
|
||||
"default-on-public-board": "Standard auf öffentlicher Arbeitstafel",
|
||||
"show-on-public-board": "Zeige auf öffentlicher Arbeitstafel",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "འགན་འབག་མི།",
|
||||
"addmore-detail": "ཞིབ་ཕྲ་བའི་འགྲེལ་བཤད་ཁ་སྣོན།",
|
||||
"show-on-card": "ཤོག་བྱང་ཐོག་སྟོན།",
|
||||
"card-settings-this-card": "ཤོག་བྱང་འདི་གི་ཐོག་ལུ།",
|
||||
"card-settings-show-empty": "སྟོངམ་སྟོན།",
|
||||
"card-settings-show-empty-fields": "ས་སྒོ་སྟོངམ་སྟོན།",
|
||||
"show-on-minicard": "ཤོག་བྱང་ཆུང་བར་སྟོན།",
|
||||
"default-on-public-board": "མི་མང་པང་ལེབ་གུ་སྔོན་སྒྲིག",
|
||||
"show-on-public-board": "མི་མང་པང་ལེབ་གུ་སྟོན།",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Ame si wotsɔ dɔ na",
|
||||
"addmore-detail": "Tsɔ numeɖeɖe le nyatakaka geɖe me kpe ɖe eŋu",
|
||||
"show-on-card": "Fia le kaɖi dzi",
|
||||
"card-settings-this-card": "Le kaɖi sia dzi",
|
||||
"card-settings-show-empty": "Fia nusiwo me naneke mele o",
|
||||
"card-settings-show-empty-fields": "Fia teƒe siwo me naneke mele o",
|
||||
"show-on-minicard": "Fia le kaɖivi dzi",
|
||||
"default-on-public-board": "Ɖoɖo le dutoƒo ʋuɖoɖo dzi",
|
||||
"show-on-public-board": "Fia le dutoƒo ʋuɖoɖo dzi",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Υπεύθυνος",
|
||||
"addmore-detail": "Προσθέστε πιο αναλυτική περιγραφή",
|
||||
"show-on-card": "Εμφάνιση στην κάρτα",
|
||||
"card-settings-this-card": "Σε αυτή την κάρτα",
|
||||
"card-settings-show-empty": "Εμφάνιση κενών",
|
||||
"card-settings-show-empty-fields": "Εμφάνιση κενών πεδίων",
|
||||
"show-on-minicard": "Εμφάνιση στη μίνι κάρτα",
|
||||
"default-on-public-board": "Προεπιλογή σε δημόσιο πίνακα",
|
||||
"show-on-public-board": "Εμφάνιση σε δημόσιο πίνακα",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Υπεύθυνος",
|
||||
"addmore-detail": "Προσθέστε πιο αναλυτική περιγραφή",
|
||||
"show-on-card": "Εμφάνιση στην κάρτα",
|
||||
"card-settings-this-card": "Σε αυτή την κάρτα",
|
||||
"card-settings-show-empty": "Εμφάνιση κενών",
|
||||
"card-settings-show-empty-fields": "Εμφάνιση κενών πεδίων",
|
||||
"show-on-minicard": "Εμφάνιση στη μίνι κάρτα",
|
||||
"default-on-public-board": "Προεπιλογή σε δημόσιο πίνακα",
|
||||
"show-on-public-board": "Εμφάνιση σε δημόσιο πίνακα",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assignee",
|
||||
"addmore-detail": "Add a more detailed description",
|
||||
"show-on-card": "Show on Card",
|
||||
"card-settings-this-card": "On this card",
|
||||
"card-settings-show-empty": "Show empty",
|
||||
"card-settings-show-empty-fields": "Show empty fields",
|
||||
"show-on-minicard": "Show on Minicard",
|
||||
"default-on-public-board": "Default on Public Board",
|
||||
"show-on-public-board": "Show on Public Board",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignito",
|
||||
"addmore-detail": "Aldoni pli detalan priskribon",
|
||||
"show-on-card": "Montri sur karto",
|
||||
"card-settings-this-card": "Sur ĉi tiu karto",
|
||||
"card-settings-show-empty": "Montri malplenajn",
|
||||
"card-settings-show-empty-fields": "Montri malplenajn kampojn",
|
||||
"show-on-minicard": "Montri sur minikarto",
|
||||
"default-on-public-board": "Defaŭlta sur publika tabulo",
|
||||
"show-on-public-board": "Montri sur publika tabulo",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Agregar una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Asignado",
|
||||
"addmore-detail": "Añadir una descripción detallada",
|
||||
"show-on-card": "Mostrar en la tarjeta",
|
||||
"card-settings-this-card": "En esta tarjeta",
|
||||
"card-settings-show-empty": "Mostrar vacíos",
|
||||
"card-settings-show-empty-fields": "Mostrar campos vacíos",
|
||||
"show-on-minicard": "Mostrar en la minitarjeta",
|
||||
"default-on-public-board": "Predeterminado en tablero público",
|
||||
"show-on-public-board": "Mostrar en tablero público",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Vastuvõtja",
|
||||
"addmore-detail": "Lisage üksikasjalikum kirjeldus",
|
||||
"show-on-card": "Näita kaardil",
|
||||
"card-settings-this-card": "Sellel kaardil",
|
||||
"card-settings-show-empty": "Näita tühje",
|
||||
"card-settings-show-empty-fields": "Näita tühje välju",
|
||||
"show-on-minicard": "Näita minikaardil",
|
||||
"default-on-public-board": "Vaikimisi avalikul tahvlil",
|
||||
"show-on-public-board": "Näita avalikul tahvlil",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Esleitua",
|
||||
"addmore-detail": "Gehitu deskripzio zehatzagoa",
|
||||
"show-on-card": "Erakutsi txartelan",
|
||||
"card-settings-this-card": "Txartel honetan",
|
||||
"card-settings-show-empty": "Erakutsi hutsak",
|
||||
"card-settings-show-empty-fields": "Erakutsi eremu hutsak",
|
||||
"show-on-minicard": "Erakutsi minitxartelean",
|
||||
"default-on-public-board": "Lehenetsia taula publikoan",
|
||||
"show-on-public-board": "Erakutsi taula publikoan",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "محولشده",
|
||||
"addmore-detail": "افزودن توضیحات کامل تر",
|
||||
"show-on-card": "نمایش در کارت",
|
||||
"card-settings-this-card": "در این کارت",
|
||||
"card-settings-show-empty": "نمایش خالیها",
|
||||
"card-settings-show-empty-fields": "نمایش فیلدهای خالی",
|
||||
"show-on-minicard": "نمایش روی کارت کوچک",
|
||||
"default-on-public-board": "پیشفرض در برد عمومی",
|
||||
"show-on-public-board": "نمایش در برد عمومی",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "محولشده",
|
||||
"addmore-detail": "افزودن توضیحات کامل تر",
|
||||
"show-on-card": "نمایش در کارت",
|
||||
"card-settings-this-card": "در این کارت",
|
||||
"card-settings-show-empty": "نمایش خالیها",
|
||||
"card-settings-show-empty-fields": "نمایش فیلدهای خالی",
|
||||
"show-on-minicard": "نمایش روی کارت کوچک",
|
||||
"default-on-public-board": "پیشفرض در برد عمومی",
|
||||
"show-on-public-board": "نمایش در برد عمومی",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Halfinaaɗo",
|
||||
"addmore-detail": "ƈeydu cifagol ɓurɗol carɗude",
|
||||
"show-on-card": "Hollu e kartal",
|
||||
"card-settings-this-card": "E ndee kartal",
|
||||
"card-settings-show-empty": "Hollu ko woni meho",
|
||||
"card-settings-show-empty-fields": "Hollu nokkuuji meho",
|
||||
"show-on-minicard": "Hollu e kartal pamarel",
|
||||
"default-on-public-board": "Fuɗɗorde e tabal kuuɓal",
|
||||
"show-on-public-board": "Hollu e tabal kuuɓal",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Käsittelijä",
|
||||
"addmore-detail": "Lisää tarkempi kuvaus",
|
||||
"show-on-card": "Näytä kortilla",
|
||||
"card-settings-this-card": "Tällä kortilla",
|
||||
"card-settings-show-empty": "Näytä tyhjät",
|
||||
"card-settings-show-empty-fields": "Näytä tyhjät kentät",
|
||||
"show-on-minicard": "Näytä minikortilla",
|
||||
"default-on-public-board": "Oletus julkisella taululla",
|
||||
"show-on-public-board": "Näytä julkisella taululla",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "E lesi kina",
|
||||
"addmore-detail": "Kuria e dua na ivakamacala matailalai cake",
|
||||
"show-on-card": "Vakaraitaka ena Kadi",
|
||||
"card-settings-this-card": "Ena Kadi oqo",
|
||||
"card-settings-show-empty": "Vakaraitaka na lala",
|
||||
"card-settings-show-empty-fields": "Vakaraitaka na vanua lala",
|
||||
"show-on-minicard": "Vakaraitaka ena Kadi Lailai",
|
||||
"default-on-public-board": "Vakarautaki ena papa raraba",
|
||||
"show-on-public-board": "Vakaraitaka ena papa raraba",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Ábyrgdari",
|
||||
"addmore-detail": "Legg eina nágreiniligari lýsing afturat",
|
||||
"show-on-card": "Vís á korti",
|
||||
"card-settings-this-card": "Á hesum korti",
|
||||
"card-settings-show-empty": "Vís tóm",
|
||||
"card-settings-show-empty-fields": "Vís tóm teigar",
|
||||
"show-on-minicard": "Vís á smákorti",
|
||||
"default-on-public-board": "Standard á almennari talvu",
|
||||
"show-on-public-board": "Vís á almennari talvu",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Intervenant",
|
||||
"addmore-detail": "Ajouter une description plus détaillée",
|
||||
"show-on-card": "Afficher sur la carte",
|
||||
"card-settings-this-card": "Sur cette carte",
|
||||
"card-settings-show-empty": "Afficher les vides",
|
||||
"card-settings-show-empty-fields": "Afficher les champs vides",
|
||||
"show-on-minicard": "Afficher sur la mini-carte",
|
||||
"default-on-public-board": "Par défaut sur tableau public",
|
||||
"show-on-public-board": "Afficher sur tableau public",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Intervenant",
|
||||
"addmore-detail": "Ajouter une description plus détaillée",
|
||||
"show-on-card": "Afficher sur la carte",
|
||||
"card-settings-this-card": "Sur cette carte",
|
||||
"card-settings-show-empty": "Afficher les vides",
|
||||
"card-settings-show-empty-fields": "Afficher les champs vides",
|
||||
"show-on-minicard": "Afficher sur la mini-carte",
|
||||
"default-on-public-board": "Par défaut sur tableau public",
|
||||
"show-on-public-board": "Afficher sur tableau public",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Intervenant",
|
||||
"addmore-detail": "Ajouter une description plus détaillée",
|
||||
"show-on-card": "Afficher sur la carte",
|
||||
"card-settings-this-card": "Sur cette carte",
|
||||
"card-settings-show-empty": "Afficher les vides",
|
||||
"card-settings-show-empty-fields": "Afficher les champs vides",
|
||||
"show-on-minicard": "Afficher sur la mini-carte",
|
||||
"default-on-public-board": "Par défaut sur tableau public",
|
||||
"show-on-public-board": "Afficher sur tableau public",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Personne assignée",
|
||||
"addmore-detail": "Ajouter une description plus détaillée",
|
||||
"show-on-card": "Afficher sur la carte",
|
||||
"card-settings-this-card": "Sur cette carte",
|
||||
"card-settings-show-empty": "Afficher les vides",
|
||||
"card-settings-show-empty-fields": "Afficher les champs vides",
|
||||
"show-on-minicard": "Afficher sur la minicarte",
|
||||
"default-on-public-board": "Par défaut sur tableau public",
|
||||
"show-on-public-board": "Afficher sur tableau public",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Intervenant",
|
||||
"addmore-detail": "Ajouter une description plus détaillée",
|
||||
"show-on-card": "Afficher sur la carte",
|
||||
"card-settings-this-card": "Sur cette carte",
|
||||
"card-settings-show-empty": "Afficher les vides",
|
||||
"card-settings-show-empty-fields": "Afficher les champs vides",
|
||||
"show-on-minicard": "Afficher sur la mini-carte",
|
||||
"default-on-public-board": "Par défaut sur tableau public",
|
||||
"show-on-public-board": "Afficher sur tableau public",
|
||||
|
||||
@@ -2000,9 +2000,6 @@
|
||||
"cardAssigneesPopup-title": "Assegnât",
|
||||
"addmore-detail": "Zonte una descrizion più dettagliata",
|
||||
"show-on-card": "Mostre sulla cjarte",
|
||||
"card-settings-this-card": "Su cheste cjarte",
|
||||
"card-settings-show-empty": "Mostre i vueits",
|
||||
"card-settings-show-empty-fields": "Mostre i cjamps vueits",
|
||||
"show-on-minicard": "Mostre sulla minicjarte",
|
||||
"default-on-public-board": "Predefinît su la lavagne publiche",
|
||||
"show-on-public-board": "Mostre su la lavagne publiche",
|
||||
|
||||
Loaded 100 of 285 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user