mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 01:20:07 -05:00
Admin Panel / Problems: reorder, rename Security Report, and take the three Features panes.
The Problems menu now reads: Summary Performance | Security | Notifications (moved from Admin Panel / Features) Speed, Tests, CPU usage -- Security Report Impersonation Report Broken Cards, Files, Rules, Boards, Cards, Recovery "Security" is renamed "Security Report" and moved above Broken Cards, with Impersonation Report directly between the two. The rename is what makes the rest safe: the pane arriving from Features is ALSO called Security, and the two now sit in one menu. It is the English SOURCE string that changed (securityReportTitle), so every other language keeps its existing translation until that string is retranslated - no human translation is overwritten, and the key is unchanged so nothing else moved. One correction worth stating: the request named Admin Panel / SETTINGS as the home of Performance, Security and Notifications. They are Admin Panel / FEATURES panes - Settings has no entry by any of those names - so they were taken from there, which is the only place they exist. Their handlers and helpers came with them, which is the half that fails silently. All twelve helpers and twelve toggles were registered on Template.adminFeatures; Blaze resolves a helper, and delivers an event, against the template the element is IN, never an enclosing one. Left there, each pane would have rendered on Problems with every checkbox reading as unchecked and no click doing anything. Each pane is its own template now, and the shared helper/handler pair is registered on all three - a handler whose element is not in a given pane simply never fires there, so splitting them per pane would buy nothing. That leaves Admin Panel / Features with no panes at all. Its page, menu and route stay, so nothing linking there breaks and a future feature has a home, but the tab is empty until it gets one. Removing the tab is a separate decision and is not made here. Tests: 1374 passing. Thanks to xet7 !
This commit is contained in:
1 parent
dcbbb448f3
commit
4df87fd6b6
7 files changed
+282
-90
No files matched your search
@@ -9,67 +9,78 @@ template(name="adminFeatures")
|
||||
.content-body
|
||||
+leftMenu(menuItems)
|
||||
.main-body
|
||||
if isPerformanceActive
|
||||
ul.setting-detail
|
||||
li.layout-form
|
||||
.title {{_ 'cards-loading'}}
|
||||
p.description {{_ 'cards-loading-description'}}
|
||||
if isSecurityActive
|
||||
ul.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-render-links-as-plain-text
|
||||
.materialCheckBox(class="{{#if renderLinksAsPlainText}}is-checked{{/if}}")
|
||||
span {{_ 'render-links-as-plain-text'}}
|
||||
p.description {{_ 'render-links-as-plain-text-description'}}
|
||||
li
|
||||
a.flex.js-toggle-always-show-code-as-text
|
||||
.materialCheckBox(class="{{#if alwaysShowCodeAsText}}is-checked{{/if}}")
|
||||
span {{_ 'always-show-code-as-text'}}
|
||||
p.description {{_ 'always-show-code-as-text-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-all-import
|
||||
.materialCheckBox(class="{{#if disableAllImport}}is-checked{{/if}}")
|
||||
span {{_ 'disable-all-import'}}
|
||||
p.description {{_ 'disable-all-import-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-all-export
|
||||
.materialCheckBox(class="{{#if disableAllExport}}is-checked{{/if}}")
|
||||
span {{_ 'disable-all-export'}}
|
||||
p.description {{_ 'disable-all-export-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-import-avatars
|
||||
.materialCheckBox(class="{{#if disableImportAvatars}}is-checked{{/if}}")
|
||||
span {{_ 'disable-import-avatars'}}
|
||||
p.description {{_ 'disable-import-avatars-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-export-avatars
|
||||
.materialCheckBox(class="{{#if disableExportAvatars}}is-checked{{/if}}")
|
||||
span {{_ 'disable-export-avatars'}}
|
||||
p.description {{_ 'disable-export-avatars-description'}}
|
||||
li
|
||||
a.flex.js-toggle-anonymize-import-users
|
||||
.materialCheckBox(class="{{#if anonymizeImportUsers}}is-checked{{/if}}")
|
||||
span {{_ 'anonymize-import-users'}}
|
||||
p.description {{_ 'anonymize-import-users-description'}}
|
||||
li
|
||||
a.flex.js-toggle-anonymize-export-users
|
||||
.materialCheckBox(class="{{#if anonymizeExportUsers}}is-checked{{/if}}")
|
||||
span {{_ 'anonymize-export-users'}}
|
||||
p.description {{_ 'anonymize-export-users-description'}}
|
||||
if isNotificationsActive
|
||||
ul.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-disable-activities
|
||||
.materialCheckBox(class="{{#if disableActivities}}is-checked{{/if}}")
|
||||
span {{_ 'disable-activities'}}
|
||||
p.description {{_ 'disable-activities-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-notifications
|
||||
.materialCheckBox(class="{{#if disableNotifications}}is-checked{{/if}}")
|
||||
span {{_ 'disable-notifications'}}
|
||||
p.description {{_ 'disable-notifications-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-watch
|
||||
.materialCheckBox(class="{{#if disableWatch}}is-checked{{/if}}")
|
||||
span {{_ 'disable-watch'}}
|
||||
p.description {{_ 'disable-watch-description'}}
|
||||
//- The three Admin Panel / Features panes. Admin Panel / PROBLEMS renders them now
|
||||
//- (adminReports.jade); they are templates of their own so their helpers and handlers
|
||||
//- can live ON them - Blaze resolves both against the template an element is IN, never
|
||||
//- an enclosing one, so a pane that kept them on Template.adminFeatures would render
|
||||
//- on Problems and then do nothing at all.
|
||||
|
||||
//- Admin Panel / Problems / Performance.
|
||||
template(name="featuresPerformance")
|
||||
ul.setting-detail
|
||||
li.layout-form
|
||||
.title {{_ 'cards-loading'}}
|
||||
p.description {{_ 'cards-loading-description'}}
|
||||
|
||||
//- Admin Panel / Problems / Security.
|
||||
template(name="featuresSecurity")
|
||||
ul.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-render-links-as-plain-text
|
||||
.materialCheckBox(class="{{#if renderLinksAsPlainText}}is-checked{{/if}}")
|
||||
span {{_ 'render-links-as-plain-text'}}
|
||||
p.description {{_ 'render-links-as-plain-text-description'}}
|
||||
li
|
||||
a.flex.js-toggle-always-show-code-as-text
|
||||
.materialCheckBox(class="{{#if alwaysShowCodeAsText}}is-checked{{/if}}")
|
||||
span {{_ 'always-show-code-as-text'}}
|
||||
p.description {{_ 'always-show-code-as-text-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-all-import
|
||||
.materialCheckBox(class="{{#if disableAllImport}}is-checked{{/if}}")
|
||||
span {{_ 'disable-all-import'}}
|
||||
p.description {{_ 'disable-all-import-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-all-export
|
||||
.materialCheckBox(class="{{#if disableAllExport}}is-checked{{/if}}")
|
||||
span {{_ 'disable-all-export'}}
|
||||
p.description {{_ 'disable-all-export-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-import-avatars
|
||||
.materialCheckBox(class="{{#if disableImportAvatars}}is-checked{{/if}}")
|
||||
span {{_ 'disable-import-avatars'}}
|
||||
p.description {{_ 'disable-import-avatars-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-export-avatars
|
||||
.materialCheckBox(class="{{#if disableExportAvatars}}is-checked{{/if}}")
|
||||
span {{_ 'disable-export-avatars'}}
|
||||
p.description {{_ 'disable-export-avatars-description'}}
|
||||
li
|
||||
a.flex.js-toggle-anonymize-import-users
|
||||
.materialCheckBox(class="{{#if anonymizeImportUsers}}is-checked{{/if}}")
|
||||
span {{_ 'anonymize-import-users'}}
|
||||
p.description {{_ 'anonymize-import-users-description'}}
|
||||
li
|
||||
a.flex.js-toggle-anonymize-export-users
|
||||
.materialCheckBox(class="{{#if anonymizeExportUsers}}is-checked{{/if}}")
|
||||
span {{_ 'anonymize-export-users'}}
|
||||
p.description {{_ 'anonymize-export-users-description'}}
|
||||
|
||||
//- Admin Panel / Problems / Notifications.
|
||||
template(name="featuresNotifications")
|
||||
ul.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-disable-activities
|
||||
.materialCheckBox(class="{{#if disableActivities}}is-checked{{/if}}")
|
||||
span {{_ 'disable-activities'}}
|
||||
p.description {{_ 'disable-activities-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-notifications
|
||||
.materialCheckBox(class="{{#if disableNotifications}}is-checked{{/if}}")
|
||||
span {{_ 'disable-notifications'}}
|
||||
p.description {{_ 'disable-notifications-description'}}
|
||||
li
|
||||
a.flex.js-toggle-disable-watch
|
||||
.materialCheckBox(class="{{#if disableWatch}}is-checked{{/if}}")
|
||||
span {{_ 'disable-watch'}}
|
||||
p.description {{_ 'disable-watch-description'}}
|
||||
@@ -13,14 +13,12 @@ Template.adminFeatures.onCreated(function () {
|
||||
});
|
||||
|
||||
// The Features side menu, as data (docs/Design/Page/Left-Menu.md).
|
||||
const FEATURES_MENU = [
|
||||
{ id: 'performance', icon: 'fa-tachometer', labelKey: 'features-performance', emoji: true },
|
||||
{ id: 'security', icon: 'fa-shield', labelKey: 'features-security', emoji: true },
|
||||
{ id: 'notifications', icon: 'fa-bell', labelKey: 'features-notifications', emoji: true },
|
||||
];
|
||||
// Admin Panel / Features has no panes of its own any more: Performance, Security and
|
||||
// Notifications all moved to Admin Panel / Problems, below Summary. The page and its
|
||||
// menu stay so nothing that links here breaks, and so a future feature has a home.
|
||||
const FEATURES_MENU = [];
|
||||
|
||||
Template.adminFeatures.helpers({
|
||||
menuItems() {
|
||||
Template.adminFeatures.helpers({ menuItems() {
|
||||
return leftMenuData(FEATURES_MENU, Template.instance().activePane.get(), 'js-features-menu');
|
||||
},
|
||||
isPerformanceActive() {
|
||||
@@ -32,6 +30,27 @@ Template.adminFeatures.helpers({
|
||||
isNotificationsActive() {
|
||||
return Template.instance().activePane.get() === 'notifications';
|
||||
},
|
||||
});
|
||||
|
||||
// Toggle one boolean setting field, saving immediately.
|
||||
function toggleSettingField(field) {
|
||||
const setting = ReactiveCache.getCurrentSetting();
|
||||
if (setting) {
|
||||
Settings.update(setting._id, { $set: { [field]: !setting[field] } });
|
||||
}
|
||||
}
|
||||
|
||||
Template.adminFeatures.events({ 'click .js-features-menu'(event, tpl) {
|
||||
tpl.activePane.set(event.currentTarget.dataset.id);
|
||||
},
|
||||
});
|
||||
|
||||
// The three panes moved to Admin Panel / Problems, which renders them from
|
||||
// adminReports.jade. Blaze resolves a helper, and delivers an event, against the
|
||||
// template the element is IN - never an enclosing one - so each pane needs these ON
|
||||
// it. One shared pair registered on all three: a handler whose element is not in a
|
||||
// given pane simply never fires there, so splitting them per pane would buy nothing.
|
||||
const featurePaneHelpers = {
|
||||
renderLinksAsPlainText() {
|
||||
return (ReactiveCache.getCurrentSetting() || {}).renderLinksAsPlainText;
|
||||
},
|
||||
@@ -65,20 +84,8 @@ Template.adminFeatures.helpers({
|
||||
disableWatch() {
|
||||
return (ReactiveCache.getCurrentSetting() || {}).disableWatch;
|
||||
},
|
||||
});
|
||||
|
||||
// Toggle one boolean setting field, saving immediately.
|
||||
function toggleSettingField(field) {
|
||||
const setting = ReactiveCache.getCurrentSetting();
|
||||
if (setting) {
|
||||
Settings.update(setting._id, { $set: { [field]: !setting[field] } });
|
||||
}
|
||||
}
|
||||
|
||||
Template.adminFeatures.events({
|
||||
'click .js-features-menu'(event, tpl) {
|
||||
tpl.activePane.set(event.currentTarget.dataset.id);
|
||||
},
|
||||
};
|
||||
const featurePaneEvents = {
|
||||
'click .js-toggle-render-links-as-plain-text'() {
|
||||
toggleSettingField('renderLinksAsPlainText');
|
||||
},
|
||||
@@ -112,4 +119,9 @@ Template.adminFeatures.events({
|
||||
'click .js-toggle-disable-watch'() {
|
||||
toggleSettingField('disableWatch');
|
||||
},
|
||||
});
|
||||
};
|
||||
for (const tpl of [Template.featuresPerformance, Template.featuresSecurity,
|
||||
Template.featuresNotifications]) {
|
||||
tpl.helpers(featurePaneHelpers);
|
||||
tpl.events(featurePaneEvents);
|
||||
}
|
||||
@@ -11,6 +11,14 @@ template(name="adminReports")
|
||||
+spinner
|
||||
else if showSummary.get
|
||||
+problemsSummary
|
||||
//- Moved here from Admin Panel / Features; the pane templates live in
|
||||
//- adminFeatures.jade with their handlers.
|
||||
else if showFeaturesPerformance.get
|
||||
+featuresPerformance
|
||||
else if showFeaturesSecurity.get
|
||||
+featuresSecurity
|
||||
else if showFeaturesNotifications.get
|
||||
+featuresNotifications
|
||||
else if showSecurity.get
|
||||
+eventStreamReport(stream="security")
|
||||
else if showSpeed.get
|
||||
|
||||
@@ -74,6 +74,10 @@ Template.adminReports.onCreated(function () {
|
||||
this.subscription = null;
|
||||
// Problems page opens on the Summary tab (the acknowledge checkbox list).
|
||||
this.showSummary = new ReactiveVar(true);
|
||||
// The three panes moved here from Admin Panel / Features.
|
||||
this.showFeaturesPerformance = new ReactiveVar(false);
|
||||
this.showFeaturesSecurity = new ReactiveVar(false);
|
||||
this.showFeaturesNotifications = new ReactiveVar(false);
|
||||
this.showSecurity = new ReactiveVar(false);
|
||||
this.showSpeed = new ReactiveVar(false);
|
||||
this.showTests = new ReactiveVar(false);
|
||||
@@ -179,17 +183,25 @@ Template.adminReports.onCreated(function () {
|
||||
// are now the single .js-left-menu-item one below.
|
||||
const PROBLEMS_MENU = [
|
||||
{ id: 'report-summary', icon: 'fa-list', labelKey: 'summary' },
|
||||
{ id: 'report-security', icon: 'fa-shield', labelKey: 'securityReportTitle' },
|
||||
// Moved here from Admin Panel / Features. They are settings rather than reports,
|
||||
// but they are what an admin reaches for when something is slow, unsafe or noisy -
|
||||
// which is what this page is about.
|
||||
{ id: 'features-performance', icon: 'fa-tachometer', labelKey: 'features-performance', emoji: true },
|
||||
{ id: 'features-security', icon: 'fa-shield', labelKey: 'features-security', emoji: true },
|
||||
{ id: 'features-notifications', icon: 'fa-bell', labelKey: 'features-notifications', emoji: true },
|
||||
{ id: 'report-speed', icon: 'fa-tachometer', labelKey: 'speedReportTitle' },
|
||||
{ id: 'report-tests', icon: 'fa-flask', labelKey: 'testsReportTitle' },
|
||||
{ id: 'report-cpu', icon: 'fa-tachometer', labelKey: 'cpuReportTitle' },
|
||||
{ separator: true },
|
||||
// "Security Report", not "Security": the Features pane above is also called
|
||||
// Security, and the two now sit in the same menu.
|
||||
{ id: 'report-security', icon: 'fa-shield', labelKey: 'securityReportTitle' },
|
||||
{ id: 'report-impersonation', icon: 'fa-user-secret', labelKey: 'impersonationReportTitle' },
|
||||
{ id: 'report-broken', icon: 'fa-chain-broken', labelKey: 'broken-cards' },
|
||||
{ id: 'report-files', icon: 'fa-paperclip', labelKey: 'filesReportTitle' },
|
||||
{ id: 'report-rules', icon: 'fa-magic', labelKey: 'rulesReportTitle' },
|
||||
{ id: 'report-boards', icon: 'fa-columns', labelKey: 'boardsReportTitle' },
|
||||
{ id: 'report-cards', icon: 'fa-id-card-o', labelKey: 'cardsReportTitle' },
|
||||
{ id: 'report-impersonation', icon: 'fa-user-secret', labelKey: 'impersonationReportTitle' },
|
||||
{ id: 'report-recovery', icon: 'fa-medkit', labelKey: 'recoveryReportTitle' },
|
||||
];
|
||||
|
||||
@@ -207,6 +219,15 @@ Template.adminReports.helpers({
|
||||
showSummary() {
|
||||
return Template.instance().showSummary;
|
||||
},
|
||||
showFeaturesPerformance() {
|
||||
return Template.instance().showFeaturesPerformance;
|
||||
},
|
||||
showFeaturesSecurity() {
|
||||
return Template.instance().showFeaturesSecurity;
|
||||
},
|
||||
showFeaturesNotifications() {
|
||||
return Template.instance().showFeaturesNotifications;
|
||||
},
|
||||
showSecurity() {
|
||||
return Template.instance().showSecurity;
|
||||
},
|
||||
@@ -336,6 +357,9 @@ function switchMenu(event, tmpl) {
|
||||
if (targetID && targetID !== tmpl.activeReport.get()) {
|
||||
tmpl.loading.set(true);
|
||||
tmpl.showSummary.set(false);
|
||||
tmpl.showFeaturesPerformance.set(false);
|
||||
tmpl.showFeaturesSecurity.set(false);
|
||||
tmpl.showFeaturesNotifications.set(false);
|
||||
tmpl.showSecurity.set(false);
|
||||
tmpl.showSpeed.set(false);
|
||||
tmpl.showTests.set(false);
|
||||
@@ -352,6 +376,16 @@ function switchMenu(event, tmpl) {
|
||||
if ('report-summary' === targetID) {
|
||||
tmpl.showSummary.set(true);
|
||||
tmpl.loading.set(false);
|
||||
} else if ('features-performance' === targetID) {
|
||||
// Settings panes: nothing to fetch, so show and clear the spinner.
|
||||
tmpl.showFeaturesPerformance.set(true);
|
||||
tmpl.loading.set(false);
|
||||
} else if ('features-security' === targetID) {
|
||||
tmpl.showFeaturesSecurity.set(true);
|
||||
tmpl.loading.set(false);
|
||||
} else if ('features-notifications' === targetID) {
|
||||
tmpl.showFeaturesNotifications.set(true);
|
||||
tmpl.loading.set(false);
|
||||
} else if ('report-security' === targetID) {
|
||||
tmpl.showSecurity.set(true);
|
||||
tmpl.loading.set(false);
|
||||
|
||||
@@ -1604,7 +1604,7 @@
|
||||
"filename-invisible-legend": "Red: filename has invisible characters",
|
||||
"reports": "Reports",
|
||||
"problems": "Problems",
|
||||
"securityReportTitle": "Security",
|
||||
"securityReportTitle": "Security Report",
|
||||
"speedReportTitle": "Speed",
|
||||
"testsReportTitle": "Tests",
|
||||
"cpuReportTitle": "CPU usage",
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"test": "meteor test --once --driver-package meteortesting:mocha",
|
||||
"test:unit:node": "node tests/filenameSanitizer.test.cjs && node tests/cardBoardConsistency.test.cjs && node tests/cardUrl.test.cjs && node tests/defaultSwimlane.test.cjs && node tests/cardMoveModifier.test.cjs && node tests/authenticationMethod.test.cjs && node tests/linkedCardTarget.test.cjs && node tests/staleWhileRevalidate.test.cjs && node tests/restArrayParam.test.cjs && node tests/minicardLabelHeight.test.cjs && node tests/dateUtils.normalizeDigits.test.cjs && node tests/reconcileBoardTeamMembers.test.cjs && node tests/rulesBoardSelector.test.cjs && node tests/ruleActionResolve.test.cjs && node tests/boardBackground.test.cjs && node tests/weekStart.test.cjs && node tests/ldapUsernameSlug.test.cjs && node tests/ldapGroupAllowlist.test.cjs && node tests/ldapConnectionRelease.test.cjs && node tests/htmljsArrayContent.test.cjs && node tests/cardDescriptionDraft.test.cjs && node tests/commentDraft.test.cjs && node tests/attachmentDeleteGuard.test.cjs && node tests/ruleMoveAction.test.cjs && node tests/snapMigrationRecovery.test.cjs && node tests/migrationAttachmentExtraction.test.cjs && node tests/attachmentRepair.test.cjs && node tests/attachmentStoragePath.test.cjs && node tests/schemaUpgradeSteps.test.cjs && node tests/cpuExec.test.cjs && node tests/cpuExecWiring.test.cjs && node tests/ferretdbHasData.test.cjs && node tests/ferretdbPolling.test.cjs && node tests/ferretdbWaitTimeout.test.cjs && node tests/ferretdbOplog.test.cjs && node tests/ferretdbOplogReset.test.cjs && node tests/ferretdbTextDataBackup.test.cjs && node tests/recoveryPlan.test.cjs && node tests/recoveryReportQuery.test.cjs && node tests/recoveryEventsJsonl.test.cjs && node tests/recoveryReportWiring.test.cjs && node tests/recoveryMaintenance.test.cjs && node tests/importMemberMapping.test.cjs && node tests/boardMemberMapPlan.test.cjs && node tests/withDeadline.test.cjs && node tests/importVirtualMembers.test.cjs && node tests/sandstormMigrationBridge.test.cjs && node tests/fileNameDisplay.test.cjs && node tests/uploadFileName.test.cjs && node tests/diskSpace.test.cjs && node tests/fileTypeCorrection.test.cjs && node tests/fileHardeningGuards.test.cjs && node tests/cpuHighTracker.test.cjs && node tests/cpuMonitorWiring.test.cjs && node tests/buttonThemeColors.test.cjs && node tests/uiDensity.test.cjs && node tests/editorSubmitKey.test.cjs && node tests/isoWeek.test.cjs && node tests/boardCopyDefaults.test.cjs && node tests/linkedCardTitle.test.cjs && node tests/commentActivity.test.cjs && node tests/swimlaneSort.test.cjs && node tests/subtaskCopy.test.cjs && node tests/subtasksDefaultBoard.test.cjs && node tests/scrollbarCss.test.cjs && node tests/minicardBidiIsolation.test.cjs && node tests/notificationCleanup.test.cjs && node tests/cardSearch.test.cjs && node tests/linkedCardMembers.test.cjs && node tests/verificationEmail.test.cjs && node tests/boardSortReorder.test.cjs && node tests/checklistItemTitles.test.cjs && node tests/swimlaneFilter.test.cjs && node tests/popupOffset.test.cjs && node tests/popupAfterConfirm.test.cjs && node tests/defaultBoard.test.cjs && node tests/upcomingUiGuards.test.cjs && node tests/linkedCardCover.test.cjs && node tests/inviteEmailLanguage.test.cjs && node tests/domainTablePage.test.cjs && node tests/mongoSelectorSafety.test.cjs && node tests/filterDateNull.test.cjs && node tests/listMoveSwimlane.test.cjs && node tests/cardDragSwimlaneScrollRefresh.test.cjs && node tests/undoRedoSelection.test.cjs && node tests/softDelete.test.cjs && node tests/globalThemeColor.test.cjs && node tests/themeCategories.test.cjs && node tests/themeColorPicker.test.cjs && node tests/uiFonts.test.cjs && node tests/sandstormAutoOpen.test.cjs && node tests/createListParams.test.cjs && node tests/addBoardTileHeight.test.cjs && node tests/multiSelectionButton.test.cjs && node tests/headerHamburger.test.cjs && node tests/changeLanguageColumns.test.cjs && node tests/cardsLoading.test.cjs && node tests/base64Chunk.test.cjs && node tests/backupPaths.test.cjs && node tests/zipbleed.test.cjs && node tests/backupCron.test.cjs && node tests/avatarUrlSafety.test.cjs && node tests/changeAvatarPopup.test.cjs && node tests/devOverlayRuntimeErrors.test.cjs && node tests/boardHeaderOneLine.test.cjs && node tests/headerDragscroll.test.cjs && node tests/jadeCompiles.test.cjs && node tests/mobileModeFullWidth.test.cjs && node tests/minicardDragHandle.test.cjs && node tests/mobileModeConsistency.test.cjs && node tests/mobileAddList.test.cjs && node tests/mobileBoardFit.test.cjs && node tests/translationPane.test.cjs && node tests/securityReportScript.test.cjs && node tests/tablePage.test.cjs && node tests/leftMenu.test.cjs && node tests/loginEmailPanesMoved.test.cjs && node tests/templateHandlersExist.test.cjs && node tests/noViewportSpacing.test.cjs && node tests/boardsVisibilitySettings.test.cjs && node tests/snapMigrationSwitchOrder.test.cjs && node tests/importedUserReconciliationPlan.test.cjs && node tests/ldapPhoto.test.cjs && node tesLine truncated
|
||||
"test:unit:node": "node tests/filenameSanitizer.test.cjs && node tests/cardBoardConsistency.test.cjs && node tests/cardUrl.test.cjs && node tests/defaultSwimlane.test.cjs && node tests/cardMoveModifier.test.cjs && node tests/authenticationMethod.test.cjs && node tests/linkedCardTarget.test.cjs && node tests/staleWhileRevalidate.test.cjs && node tests/restArrayParam.test.cjs && node tests/minicardLabelHeight.test.cjs && node tests/dateUtils.normalizeDigits.test.cjs && node tests/reconcileBoardTeamMembers.test.cjs && node tests/rulesBoardSelector.test.cjs && node tests/ruleActionResolve.test.cjs && node tests/boardBackground.test.cjs && node tests/weekStart.test.cjs && node tests/ldapUsernameSlug.test.cjs && node tests/ldapGroupAllowlist.test.cjs && node tests/ldapConnectionRelease.test.cjs && node tests/htmljsArrayContent.test.cjs && node tests/cardDescriptionDraft.test.cjs && node tests/commentDraft.test.cjs && node tests/attachmentDeleteGuard.test.cjs && node tests/ruleMoveAction.test.cjs && node tests/snapMigrationRecovery.test.cjs && node tests/migrationAttachmentExtraction.test.cjs && node tests/attachmentRepair.test.cjs && node tests/attachmentStoragePath.test.cjs && node tests/schemaUpgradeSteps.test.cjs && node tests/cpuExec.test.cjs && node tests/cpuExecWiring.test.cjs && node tests/ferretdbHasData.test.cjs && node tests/ferretdbPolling.test.cjs && node tests/ferretdbWaitTimeout.test.cjs && node tests/ferretdbOplog.test.cjs && node tests/ferretdbOplogReset.test.cjs && node tests/ferretdbTextDataBackup.test.cjs && node tests/recoveryPlan.test.cjs && node tests/recoveryReportQuery.test.cjs && node tests/recoveryEventsJsonl.test.cjs && node tests/recoveryReportWiring.test.cjs && node tests/recoveryMaintenance.test.cjs && node tests/importMemberMapping.test.cjs && node tests/boardMemberMapPlan.test.cjs && node tests/withDeadline.test.cjs && node tests/importVirtualMembers.test.cjs && node tests/sandstormMigrationBridge.test.cjs && node tests/fileNameDisplay.test.cjs && node tests/uploadFileName.test.cjs && node tests/diskSpace.test.cjs && node tests/fileTypeCorrection.test.cjs && node tests/fileHardeningGuards.test.cjs && node tests/cpuHighTracker.test.cjs && node tests/cpuMonitorWiring.test.cjs && node tests/buttonThemeColors.test.cjs && node tests/uiDensity.test.cjs && node tests/editorSubmitKey.test.cjs && node tests/isoWeek.test.cjs && node tests/boardCopyDefaults.test.cjs && node tests/linkedCardTitle.test.cjs && node tests/commentActivity.test.cjs && node tests/swimlaneSort.test.cjs && node tests/subtaskCopy.test.cjs && node tests/subtasksDefaultBoard.test.cjs && node tests/scrollbarCss.test.cjs && node tests/minicardBidiIsolation.test.cjs && node tests/notificationCleanup.test.cjs && node tests/cardSearch.test.cjs && node tests/linkedCardMembers.test.cjs && node tests/verificationEmail.test.cjs && node tests/boardSortReorder.test.cjs && node tests/checklistItemTitles.test.cjs && node tests/swimlaneFilter.test.cjs && node tests/popupOffset.test.cjs && node tests/popupAfterConfirm.test.cjs && node tests/defaultBoard.test.cjs && node tests/upcomingUiGuards.test.cjs && node tests/linkedCardCover.test.cjs && node tests/inviteEmailLanguage.test.cjs && node tests/domainTablePage.test.cjs && node tests/mongoSelectorSafety.test.cjs && node tests/filterDateNull.test.cjs && node tests/listMoveSwimlane.test.cjs && node tests/cardDragSwimlaneScrollRefresh.test.cjs && node tests/undoRedoSelection.test.cjs && node tests/softDelete.test.cjs && node tests/globalThemeColor.test.cjs && node tests/themeCategories.test.cjs && node tests/themeColorPicker.test.cjs && node tests/uiFonts.test.cjs && node tests/sandstormAutoOpen.test.cjs && node tests/createListParams.test.cjs && node tests/addBoardTileHeight.test.cjs && node tests/multiSelectionButton.test.cjs && node tests/headerHamburger.test.cjs && node tests/changeLanguageColumns.test.cjs && node tests/cardsLoading.test.cjs && node tests/base64Chunk.test.cjs && node tests/backupPaths.test.cjs && node tests/zipbleed.test.cjs && node tests/backupCron.test.cjs && node tests/avatarUrlSafety.test.cjs && node tests/changeAvatarPopup.test.cjs && node tests/devOverlayRuntimeErrors.test.cjs && node tests/boardHeaderOneLine.test.cjs && node tests/headerDragscroll.test.cjs && node tests/jadeCompiles.test.cjs && node tests/mobileModeFullWidth.test.cjs && node tests/minicardDragHandle.test.cjs && node tests/mobileModeConsistency.test.cjs && node tests/mobileAddList.test.cjs && node tests/mobileBoardFit.test.cjs && node tests/translationPane.test.cjs && node tests/securityReportScript.test.cjs && node tests/tablePage.test.cjs && node tests/leftMenu.test.cjs && node tests/loginEmailPanesMoved.test.cjs && node tests/problemsMenuOrder.test.cjs && node tests/templateHandlersExist.test.cjs && node tests/noViewportSpacing.test.cjs && node tests/boardsVisibilitySettings.test.cjs && node tests/snapMigrationSwitchOrder.test.cjs && node tests/importedUserReconciliationPlan.test.cjs && Line truncated
|
||||
"test:unit:all": "npm run test:unit:node && node tests/cards.stickers.test.js && node tests/stickers.test.js && node tests/stickers.packs.test.js && node tests/linkCardPopup.test.js && node tests/trelloCreator.import.test.js && node tests/trelloImport.maplink.test.js && node tests/trelloImport.zip.test.js && node tests/wekanCreator.import.test.js && node tests/wekanCreator.inconsistent.test.js && node tests/unit/oauth2-admin-groups.test.js",
|
||||
"test:watch": "meteor test --driver-package meteortesting:mocha",
|
||||
"test:e2e": "node tests/e2e/list-regressions.js",
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
'use strict';
|
||||
|
||||
// Admin Panel / Problems: the menu order, the Security Report rename, and the three
|
||||
// panes that moved here from Admin Panel / Features.
|
||||
//
|
||||
// Requested:
|
||||
// * "Security" renamed to "Security Report" and moved ABOVE "Broken Cards"
|
||||
// * "Impersonation Report" moved BELOW "Security Report"
|
||||
// * Performance, Security and Notifications moved here, below "Summary"
|
||||
//
|
||||
// The rename is what makes the rest safe: the pane arriving from Features is ALSO
|
||||
// called Security, and the two now sit in one menu. Renaming the report is the source
|
||||
// string changing, so other languages keep their existing translation until it is
|
||||
// retranslated - a human translation is never overwritten.
|
||||
//
|
||||
// The pane move has the same trap as every other move in this series: the helpers and
|
||||
// handlers were on Template.adminFeatures, and Blaze resolves a helper - and delivers
|
||||
// an event - against the template the element is IN, never an enclosing one. Left
|
||||
// there, each pane would render on Problems and then do nothing at all.
|
||||
//
|
||||
// Run: node tests/problemsMenuOrder.test.cjs
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let passed = 0;
|
||||
function test(name, fn) { fn(); passed += 1; console.log(' ok -', name); }
|
||||
|
||||
const root = path.join(__dirname, '..');
|
||||
const read = rel => fs.readFileSync(path.join(root, rel), 'utf8');
|
||||
|
||||
const reportsJs = read('client/components/settings/adminReports.js');
|
||||
const reportsJade = read('client/components/settings/adminReports.jade');
|
||||
const featuresJs = read('client/components/settings/adminFeatures.js');
|
||||
const featuresJade = read('client/components/settings/adminFeatures.jade');
|
||||
const en = JSON.parse(read('imports/i18n/data/en.i18n.json'));
|
||||
|
||||
const menu = reportsJs.slice(reportsJs.indexOf('const PROBLEMS_MENU'),
|
||||
reportsJs.indexOf('];', reportsJs.indexOf('const PROBLEMS_MENU')));
|
||||
const at = id => menu.indexOf(`id: '${id}'`);
|
||||
|
||||
console.log('problemsMenuOrder:');
|
||||
|
||||
test('Security Report sits above Broken Cards, with Impersonation between', () => {
|
||||
assert.ok(at('report-security') > -1 && at('report-broken') > -1
|
||||
&& at('report-impersonation') > -1, 'all three entries must exist');
|
||||
assert.ok(at('report-security') < at('report-broken'),
|
||||
'Security Report is above Broken Cards');
|
||||
assert.ok(at('report-impersonation') > at('report-security'),
|
||||
'Impersonation Report is below Security Report');
|
||||
assert.ok(at('report-impersonation') < at('report-broken'),
|
||||
'and still above Broken Cards, i.e. directly between the two');
|
||||
});
|
||||
|
||||
test('the report is called Security Report, in the source string', () => {
|
||||
assert.strictEqual(en.securityReportTitle, 'Security Report');
|
||||
// The menu still points at the same key, so no pane lost its translations - only
|
||||
// the English source changed, and Transifex marks it for retranslation.
|
||||
assert.ok(/id: 'report-security'[^}]*labelKey: 'securityReportTitle'/.test(menu));
|
||||
// It has to differ from the Features pane it now shares a menu with.
|
||||
assert.notStrictEqual(en.securityReportTitle, en['features-security'],
|
||||
'two entries in one menu must not both read "Security"');
|
||||
});
|
||||
|
||||
test('Performance, Security and Notifications sit below Summary', () => {
|
||||
for (const id of ['features-performance', 'features-security', 'features-notifications']) {
|
||||
assert.ok(at(id) > -1, `${id} must be a Problems entry`);
|
||||
assert.ok(at(id) > at('report-summary'), `${id} must be below Summary`);
|
||||
}
|
||||
// In their original order, and above the reports that were already here.
|
||||
assert.ok(at('features-performance') < at('features-security'));
|
||||
assert.ok(at('features-security') < at('features-notifications'));
|
||||
assert.ok(at('features-notifications') < at('report-speed'));
|
||||
});
|
||||
|
||||
test('Problems renders all three right-hand pages', () => {
|
||||
for (const [flag, tpl] of [['showFeaturesPerformance', 'featuresPerformance'],
|
||||
['showFeaturesSecurity', 'featuresSecurity'],
|
||||
['showFeaturesNotifications', 'featuresNotifications']]) {
|
||||
assert.ok(new RegExp(`else if ${flag}\\.get\\s*\\n\\s*\\+${tpl}`).test(reportsJade),
|
||||
`${tpl} must be rendered`);
|
||||
// With the state behind it, or the branch is never true.
|
||||
assert.ok(reportsJs.includes(`this.${flag} = new ReactiveVar(false)`), `${flag} must exist`);
|
||||
assert.ok(reportsJs.includes(`tmpl.${flag}.set(false)`), `${flag} must be reset on a switch`);
|
||||
assert.ok(reportsJs.includes(`tmpl.${flag}.set(true)`), `${flag} must be set by its entry`);
|
||||
assert.ok(new RegExp(` ${flag}\\(\\) \\{`).test(reportsJs), `${flag} needs a helper`);
|
||||
}
|
||||
// And the templates they render must exist.
|
||||
for (const tpl of ['featuresPerformance', 'featuresSecurity', 'featuresNotifications']) {
|
||||
assert.ok(featuresJade.includes(`template(name="${tpl}")`), `template ${tpl} must exist`);
|
||||
}
|
||||
});
|
||||
|
||||
test('each pane took its helpers and handlers with it', () => {
|
||||
// The half that fails silently: the pane renders, every checkbox reads as unchecked
|
||||
// and no click does anything.
|
||||
assert.ok(/const featurePaneHelpers = \{/.test(featuresJs), 'the pane helpers are their own object');
|
||||
assert.ok(/const featurePaneEvents = \{/.test(featuresJs), 'and so are the handlers');
|
||||
assert.ok(/for \(const tpl of \[Template\.featuresPerformance, Template\.featuresSecurity,[\s\S]{0,80}tpl\.helpers\(featurePaneHelpers\);[\s\S]{0,40}tpl\.events\(featurePaneEvents\);/
|
||||
.test(featuresJs), 'registered on all three pane templates');
|
||||
// They must NOT be left on the page template.
|
||||
const pageHelpers = /Template\.adminFeatures\.helpers\(\{([\s\S]*?)\n\}\);/.exec(featuresJs)[1];
|
||||
const pageEvents = /Template\.adminFeatures\.events\(\{([\s\S]*?)\n\}\);/.exec(featuresJs)[1];
|
||||
for (const helper of ['renderLinksAsPlainText', 'disableAllImport', 'disableWatch']) {
|
||||
assert.ok(!pageHelpers.includes(`${helper}()`), `${helper} must be on the pane, not the page`);
|
||||
assert.ok(/const featurePaneHelpers[\s\S]*?/.test(featuresJs)
|
||||
&& featuresJs.slice(featuresJs.indexOf('const featurePaneHelpers')).includes(`${helper}()`),
|
||||
`${helper} must be in the pane helpers`);
|
||||
}
|
||||
for (const cls of ['js-toggle-render-links-as-plain-text', 'js-toggle-disable-all-export',
|
||||
'js-toggle-disable-notifications']) {
|
||||
assert.ok(!pageEvents.includes(cls), `${cls} must be on the pane, not the page`);
|
||||
}
|
||||
// The menu handler is the page's own and stays.
|
||||
assert.ok(pageEvents.includes('js-features-menu'), 'the page keeps its own menu handler');
|
||||
});
|
||||
|
||||
test('Features is left empty but intact (negative)', () => {
|
||||
assert.ok(/const FEATURES_MENU = \[\];/.test(featuresJs),
|
||||
'its menu has no entries left - all three moved');
|
||||
// The page still renders, so nothing linking to it breaks.
|
||||
assert.ok(/template\(name="adminFeatures"\)/.test(featuresJade), 'the page still exists');
|
||||
assert.ok(/leftMenuData\(FEATURES_MENU/.test(featuresJs), 'and still builds its menu the shared way');
|
||||
});
|
||||
|
||||
console.log(`\nproblemsMenuOrder: ${passed} tests passed`);
|
||||
Reference in new issue
Block a user