mirror of
https://github.com/apache/superset.git
synced 2026-05-03 15:04:28 +00:00
Compare commits
1 Commits
docs/testi
...
eslit-no-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16b4ec347d |
@@ -403,6 +403,7 @@ module.exports = {
|
|||||||
'theme-colors/no-literal-colors': 'error',
|
'theme-colors/no-literal-colors': 'error',
|
||||||
'icons/no-fa-icons-usage': 'error',
|
'icons/no-fa-icons-usage': 'error',
|
||||||
'i18n-strings/no-template-vars': ['error', true],
|
'i18n-strings/no-template-vars': ['error', true],
|
||||||
|
'i18n-strings/no-title-case': 'error',
|
||||||
camelcase: [
|
camelcase: [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ module.exports = {
|
|||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
message:
|
message:
|
||||||
"Don't use variables in translation string templates. Flask-babel is a static translation service, so it can’t handle strings that include variables",
|
"Don't use variables in translation string templates. Flask-babel is a static translation service, so it can't handle strings that include variables",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,5 +52,134 @@ module.exports = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'no-title-case': {
|
||||||
|
create(context) {
|
||||||
|
function checkTitleCase(str) {
|
||||||
|
// Skip strings with placeholders like %s, %d, %(name)s, etc.
|
||||||
|
if (/%[sdf]|%\([^)]+\)[sdf]/.test(str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip strings that are all uppercase (likely acronyms)
|
||||||
|
if (str === str.toUpperCase()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip strings with periods (likely multiple sentences)
|
||||||
|
if (str.includes('.')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip single words
|
||||||
|
const words = str.trim().split(/\s+/);
|
||||||
|
if (words.length <= 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whitelist of words that are commonly capitalized in product names
|
||||||
|
// but should not trigger title case warnings
|
||||||
|
const productWords = [
|
||||||
|
'Lab',
|
||||||
|
'Server',
|
||||||
|
'Studio',
|
||||||
|
'Pro',
|
||||||
|
'Plus',
|
||||||
|
'Max',
|
||||||
|
'Mini',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Common prepositions and articles that should be lowercase (unless at start)
|
||||||
|
const lowercaseWords = [
|
||||||
|
'a',
|
||||||
|
'an',
|
||||||
|
'the',
|
||||||
|
'and',
|
||||||
|
'or',
|
||||||
|
'but',
|
||||||
|
'for',
|
||||||
|
'with',
|
||||||
|
'to',
|
||||||
|
'from',
|
||||||
|
'in',
|
||||||
|
'on',
|
||||||
|
'at',
|
||||||
|
'by',
|
||||||
|
'of',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if the string uses title case (multiple words with first letter capitalized)
|
||||||
|
const hasTitleCase = words.some((word, index) => {
|
||||||
|
// Skip first word
|
||||||
|
if (index === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip acronyms (all uppercase)
|
||||||
|
if (word === word.toUpperCase()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip whitelisted product words when preceded by an uppercase word
|
||||||
|
if (
|
||||||
|
productWords.includes(word) &&
|
||||||
|
index > 0 &&
|
||||||
|
words[index - 1] === words[index - 1].toUpperCase()
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's a lowercase word that's incorrectly capitalized
|
||||||
|
if (
|
||||||
|
lowercaseWords.includes(word.toLowerCase()) &&
|
||||||
|
/^[A-Z]/.test(word)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other words, check if they start with capital letter
|
||||||
|
return (
|
||||||
|
word.length > 1 &&
|
||||||
|
/^[A-Z]/.test(word) &&
|
||||||
|
!productWords.includes(word)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return hasTitleCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handler(node) {
|
||||||
|
if (node.arguments.length) {
|
||||||
|
const firstArg = node.arguments[0];
|
||||||
|
let stringValue = null;
|
||||||
|
|
||||||
|
// Extract string value based on node type
|
||||||
|
if (
|
||||||
|
firstArg.type === 'Literal' &&
|
||||||
|
typeof firstArg.value === 'string'
|
||||||
|
) {
|
||||||
|
stringValue = firstArg.value;
|
||||||
|
} else if (
|
||||||
|
firstArg.type === 'TemplateLiteral' &&
|
||||||
|
firstArg.quasis.length === 1
|
||||||
|
) {
|
||||||
|
// Handle template literals without expressions
|
||||||
|
stringValue = firstArg.quasis[0].value.raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stringValue && checkTitleCase(stringValue)) {
|
||||||
|
context.report({
|
||||||
|
node: firstArg,
|
||||||
|
message: `Avoid title case in i18n strings: "${stringValue}". Use sentence case instead.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"CallExpression[callee.name='t']": handler,
|
||||||
|
"CallExpression[callee.name='tn']": handler,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { RuleTester } = require('eslint');
|
||||||
|
const plugin = require('./index');
|
||||||
|
|
||||||
|
const ruleTester = new RuleTester({
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 6,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const rule = plugin.rules['no-title-case'];
|
||||||
|
|
||||||
|
ruleTester.run('no-title-case', rule, {
|
||||||
|
valid: [
|
||||||
|
// Sentence case (correct)
|
||||||
|
{
|
||||||
|
code: "t('Add a divider')",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Create new dashboard')",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Save and continue')",
|
||||||
|
},
|
||||||
|
// Single words
|
||||||
|
{
|
||||||
|
code: "t('Save')",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Delete')",
|
||||||
|
},
|
||||||
|
// All uppercase (acronyms)
|
||||||
|
{
|
||||||
|
code: "t('SQL')",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('API KEY')",
|
||||||
|
},
|
||||||
|
// With placeholders
|
||||||
|
{
|
||||||
|
code: "t('Deleted: %s', name)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('User %(username)s added', { username })",
|
||||||
|
},
|
||||||
|
// Template literals without expressions
|
||||||
|
{
|
||||||
|
code: 't(`Add a new filter`)',
|
||||||
|
},
|
||||||
|
// Mixed case but not title case
|
||||||
|
{
|
||||||
|
code: "t('Use SQL Lab')",
|
||||||
|
},
|
||||||
|
// tn function
|
||||||
|
{
|
||||||
|
code: "tn('Add a filter', 'Add filters', count)",
|
||||||
|
},
|
||||||
|
// Multiple sentences with period
|
||||||
|
{
|
||||||
|
code: "t('Welcome Back. Please Login.')",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Save Changes. This Will Update All Records.')",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
invalid: [
|
||||||
|
// Title case (incorrect)
|
||||||
|
{
|
||||||
|
code: "t('Add Divider')",
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Avoid title case in i18n strings: "Add Divider". Use sentence case instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Create New Dashboard')",
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Avoid title case in i18n strings: "Create New Dashboard". Use sentence case instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Save And Continue')",
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Avoid title case in i18n strings: "Save And Continue". Use sentence case instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Add Filter')",
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Avoid title case in i18n strings: "Add Filter". Use sentence case instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "t('Edit User')",
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Avoid title case in i18n strings: "Edit User". Use sentence case instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Template literals
|
||||||
|
{
|
||||||
|
code: 't(`Add Layer`)',
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Avoid title case in i18n strings: "Add Layer". Use sentence case instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// tn function
|
||||||
|
{
|
||||||
|
code: "tn('Delete Item', 'Delete Items', count)",
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Avoid title case in i18n strings: "Delete Item". Use sentence case instead.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -30,10 +30,10 @@ export const DEFAULT_MAX_ROW_TABLE_SERVER = 500000;
|
|||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export const TIME_FILTER_LABELS = {
|
export const TIME_FILTER_LABELS = {
|
||||||
time_range: t('Time Range'),
|
time_range: t('Time range'),
|
||||||
granularity_sqla: t('Time Column'),
|
granularity_sqla: t('Time column'),
|
||||||
time_grain_sqla: t('Time Grain'),
|
time_grain_sqla: t('Time grain'),
|
||||||
granularity: t('Time Granularity'),
|
granularity: t('Time granularity'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const COLUMN_NAME_ALIASES: Record<string, string> = {
|
export const COLUMN_NAME_ALIASES: Record<string, string> = {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const ExploreResultsButton = ({
|
|||||||
tooltip={t('Explore the result set in the data exploration view')}
|
tooltip={t('Explore the result set in the data exploration view')}
|
||||||
data-test="explore-results-button"
|
data-test="explore-results-button"
|
||||||
>
|
>
|
||||||
{t('Create Chart')}
|
{t('Create chart')}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export const KEY_MAP: Record<KeyboardShortcut, string | undefined> = {
|
|||||||
[KeyboardShortcut.CtrlE]: userOS !== 'MacOS' ? t('Stop query') : undefined,
|
[KeyboardShortcut.CtrlE]: userOS !== 'MacOS' ? t('Stop query') : undefined,
|
||||||
[KeyboardShortcut.CtrlQ]: userOS === 'Windows' ? t('New tab') : undefined,
|
[KeyboardShortcut.CtrlQ]: userOS === 'Windows' ? t('New tab') : undefined,
|
||||||
[KeyboardShortcut.CtrlT]: userOS !== 'Windows' ? t('New tab') : undefined,
|
[KeyboardShortcut.CtrlT]: userOS !== 'Windows' ? t('New tab') : undefined,
|
||||||
[KeyboardShortcut.CtrlP]: t('Previous Line'),
|
[KeyboardShortcut.CtrlP]: t('Previous line'),
|
||||||
[KeyboardShortcut.CtrlShiftF]: t('Format SQL'),
|
[KeyboardShortcut.CtrlShiftF]: t('Format SQL'),
|
||||||
[KeyboardShortcut.CtrlLeft]: t('Switch to the previous tab'),
|
[KeyboardShortcut.CtrlLeft]: t('Switch to the previous tab'),
|
||||||
[KeyboardShortcut.CtrlRight]: t('Switch to the next tab'),
|
[KeyboardShortcut.CtrlRight]: t('Switch to the next tab'),
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ const updateDataset = async (
|
|||||||
return data.json.result;
|
return data.json.result;
|
||||||
};
|
};
|
||||||
|
|
||||||
const UNTITLED = t('Untitled Dataset');
|
const UNTITLED = t('Untitled dataset');
|
||||||
|
|
||||||
export const SaveDatasetModal = ({
|
export const SaveDatasetModal = ({
|
||||||
visible,
|
visible,
|
||||||
@@ -374,10 +374,10 @@ export const SaveDatasetModal = ({
|
|||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
show={visible}
|
show={visible}
|
||||||
name={t('Save or Overwrite Dataset')}
|
name={t('Save or overwrite dataset')}
|
||||||
title={
|
title={
|
||||||
<ModalTitleWithIcon
|
<ModalTitleWithIcon
|
||||||
title={t('Save or Overwrite Dataset')}
|
title={t('Save or overwrite dataset')}
|
||||||
icon={<Icons.SaveOutlined />}
|
icon={<Icons.SaveOutlined />}
|
||||||
data-test="save-or-overwrite-dataset-title"
|
data-test="save-or-overwrite-dataset-title"
|
||||||
/>
|
/>
|
||||||
@@ -394,7 +394,7 @@ export const SaveDatasetModal = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<span style={{ marginLeft: '5px' }}>
|
<span style={{ marginLeft: '5px' }}>
|
||||||
{t('Include Template Parameters')}
|
{t('Include template parameters')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -637,7 +637,7 @@ function ExploreViewContainer(props) {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="title-container">
|
<div className="title-container">
|
||||||
<span className="horizontal-text">{t('Chart Source')}</span>
|
<span className="horizontal-text">{t('Chart source')}</span>
|
||||||
<span
|
<span
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
@@ -672,7 +672,7 @@ function ExploreViewContainer(props) {
|
|||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<span role="button" tabIndex={0} className="action-button">
|
<span role="button" tabIndex={0} className="action-button">
|
||||||
<Tooltip title={t('Open Datasource tab')}>
|
<Tooltip title={t('Open datasource tab')}>
|
||||||
<Icons.VerticalAlignTopOutlined
|
<Icons.VerticalAlignTopOutlined
|
||||||
iconSize="xl"
|
iconSize="xl"
|
||||||
css={css`
|
css={css`
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ class SaveModal extends Component<SaveModalProps, SaveModalState> {
|
|||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
{this.props.datasource?.type === 'query' && (
|
{this.props.datasource?.type === 'query' && (
|
||||||
<FormItem label={t('Dataset Name')} required>
|
<FormItem label={t('Dataset name')} required>
|
||||||
<InfoTooltip
|
<InfoTooltip
|
||||||
tooltip={t('A reusable dataset will be saved with your chart.')}
|
tooltip={t('A reusable dataset will be saved with your chart.')}
|
||||||
placement="right"
|
placement="right"
|
||||||
|
|||||||
@@ -575,8 +575,8 @@ function ChartList(props: ChartListProps) {
|
|||||||
operator: FilterOperator.ChartIsFav,
|
operator: FilterOperator.ChartIsFav,
|
||||||
unfilteredLabel: t('Any'),
|
unfilteredLabel: t('Any'),
|
||||||
selects: [
|
selects: [
|
||||||
{ label: t('Yes'), value: true },
|
{ label: t('yes'), value: true },
|
||||||
{ label: t('No'), value: false },
|
{ label: t('no'), value: false },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
|
|||||||
@@ -530,8 +530,8 @@ function DashboardList(props: DashboardListProps) {
|
|||||||
operator: FilterOperator.DashboardIsFav,
|
operator: FilterOperator.DashboardIsFav,
|
||||||
unfilteredLabel: t('Any'),
|
unfilteredLabel: t('Any'),
|
||||||
selects: [
|
selects: [
|
||||||
{ label: t('Yes'), value: true },
|
{ label: t('yes'), value: true },
|
||||||
{ label: t('No'), value: false },
|
{ label: t('no'), value: false },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
@@ -604,8 +604,8 @@ function DashboardList(props: DashboardListProps) {
|
|||||||
operator: FilterOperator.DashboardIsCertified,
|
operator: FilterOperator.DashboardIsCertified,
|
||||||
unfilteredLabel: t('Any'),
|
unfilteredLabel: t('Any'),
|
||||||
selects: [
|
selects: [
|
||||||
{ label: t('Yes'), value: true },
|
{ label: t('yes'), value: true },
|
||||||
{ label: t('No'), value: false },
|
{ label: t('no'), value: false },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -530,8 +530,8 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||||||
operator: FilterOperator.DatasetIsNullOrEmpty,
|
operator: FilterOperator.DatasetIsNullOrEmpty,
|
||||||
unfilteredLabel: 'All',
|
unfilteredLabel: 'All',
|
||||||
selects: [
|
selects: [
|
||||||
{ label: t('Virtual'), value: false },
|
{ label: t('virtual'), value: false },
|
||||||
{ label: t('Physical'), value: true },
|
{ label: t('physical'), value: true },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -598,8 +598,8 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||||||
operator: FilterOperator.DatasetIsCertified,
|
operator: FilterOperator.DatasetIsCertified,
|
||||||
unfilteredLabel: t('Any'),
|
unfilteredLabel: t('Any'),
|
||||||
selects: [
|
selects: [
|
||||||
{ label: t('Yes'), value: true },
|
{ label: t('yes'), value: true },
|
||||||
{ label: t('No'), value: false },
|
{ label: t('no'), value: false },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -764,7 +764,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||||||
</p>
|
</p>
|
||||||
{datasetCurrentlyDeleting.dashboards.count >= 1 && (
|
{datasetCurrentlyDeleting.dashboards.count >= 1 && (
|
||||||
<>
|
<>
|
||||||
<h4>{t('Affected Dashboards')}</h4>
|
<h4>{t('Affected dashboards')}</h4>
|
||||||
<List
|
<List
|
||||||
split={false}
|
split={false}
|
||||||
size="small"
|
size="small"
|
||||||
@@ -807,7 +807,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||||||
)}
|
)}
|
||||||
{datasetCurrentlyDeleting.charts.count >= 1 && (
|
{datasetCurrentlyDeleting.charts.count >= 1 && (
|
||||||
<>
|
<>
|
||||||
<h4>{t('Affected Charts')}</h4>
|
<h4>{t('Affected charts')}</h4>
|
||||||
<List
|
<List
|
||||||
split={false}
|
split={false}
|
||||||
size="small"
|
size="small"
|
||||||
@@ -860,7 +860,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||||||
}}
|
}}
|
||||||
onHide={closeDatasetDeleteModal}
|
onHide={closeDatasetDeleteModal}
|
||||||
open
|
open
|
||||||
title={t('Delete Dataset?')}
|
title={t('Delete dataset?')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{datasetCurrentlyEditing && (
|
{datasetCurrentlyEditing && (
|
||||||
@@ -931,7 +931,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!selected.length) {
|
if (!selected.length) {
|
||||||
return t('0 Selected');
|
return t('0 selected');
|
||||||
}
|
}
|
||||||
if (virtualCount && !physicalCount) {
|
if (virtualCount && !physicalCount) {
|
||||||
return t(
|
return t(
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ function RowLevelSecurityList(props: RLSProps) {
|
|||||||
toggleBulkSelect,
|
toggleBulkSelect,
|
||||||
} = useListViewResource<RLSObject>(
|
} = useListViewResource<RLSObject>(
|
||||||
'rowlevelsecurity',
|
'rowlevelsecurity',
|
||||||
t('Row Level Security'),
|
t('Row level security'),
|
||||||
addDangerToast,
|
addDangerToast,
|
||||||
true,
|
true,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -130,13 +130,13 @@ function RowLevelSecurityList(props: RLSProps) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'filter_type',
|
accessor: 'filter_type',
|
||||||
Header: t('Filter Type'),
|
Header: t('Filter type'),
|
||||||
size: 'xl',
|
size: 'xl',
|
||||||
id: 'filter_type',
|
id: 'filter_type',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'group_key',
|
accessor: 'group_key',
|
||||||
Header: t('Group Key'),
|
Header: t('Group key'),
|
||||||
size: 'xl',
|
size: 'xl',
|
||||||
id: 'group_key',
|
id: 'group_key',
|
||||||
},
|
},
|
||||||
@@ -246,7 +246,7 @@ function RowLevelSecurityList(props: RLSProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const emptyState = {
|
const emptyState = {
|
||||||
title: t('No Rules yet'),
|
title: t('No rules yet'),
|
||||||
image: 'filter-results.svg',
|
image: 'filter-results.svg',
|
||||||
buttonAction: () => handleRuleEdit(null),
|
buttonAction: () => handleRuleEdit(null),
|
||||||
buttonIcon: canEdit ? (
|
buttonIcon: canEdit ? (
|
||||||
@@ -265,7 +265,7 @@ function RowLevelSecurityList(props: RLSProps) {
|
|||||||
operator: FilterOperator.StartsWith,
|
operator: FilterOperator.StartsWith,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: t('Filter Type'),
|
Header: t('Filter type'),
|
||||||
key: 'filter_type',
|
key: 'filter_type',
|
||||||
id: 'filter_type',
|
id: 'filter_type',
|
||||||
input: 'select',
|
input: 'select',
|
||||||
@@ -277,7 +277,7 @@ function RowLevelSecurityList(props: RLSProps) {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: t('Group Key'),
|
Header: t('Group key'),
|
||||||
key: 'search',
|
key: 'search',
|
||||||
id: 'group_key',
|
id: 'group_key',
|
||||||
input: 'search',
|
input: 'search',
|
||||||
@@ -329,7 +329,7 @@ function RowLevelSecurityList(props: RLSProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SubMenu name={t('Row Level Security')} buttons={subMenuButtons} />
|
<SubMenu name={t('Row level security')} buttons={subMenuButtons} />
|
||||||
<ConfirmStatusChange
|
<ConfirmStatusChange
|
||||||
title={t('Please confirm')}
|
title={t('Please confirm')}
|
||||||
description={t('Are you sure you want to delete the selected rules?')}
|
description={t('Are you sure you want to delete the selected rules?')}
|
||||||
|
|||||||
@@ -519,7 +519,7 @@ function UsersList({ user }: UsersListProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SubMenu name={t('List Users')} buttons={subMenuButtons} />
|
<SubMenu name={t('List users')} buttons={subMenuButtons} />
|
||||||
<UserListAddModal
|
<UserListAddModal
|
||||||
onHide={() => closeModal(ModalType.ADD)}
|
onHide={() => closeModal(ModalType.ADD)}
|
||||||
show={modalState.add}
|
show={modalState.add}
|
||||||
@@ -554,7 +554,7 @@ function UsersList({ user }: UsersListProps) {
|
|||||||
}}
|
}}
|
||||||
onHide={() => setUserCurrentlyDeleting(null)}
|
onHide={() => setUserCurrentlyDeleting(null)}
|
||||||
open
|
open
|
||||||
title={t('Delete User?')}
|
title={t('Delete user?')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<ConfirmStatusChange
|
<ConfirmStatusChange
|
||||||
|
|||||||
Reference in New Issue
Block a user