Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/js/codechecker-api-node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codechecker-api",
"version": "6.70.0",
"version": "6.71.0",
"description": "Generated node.js compatible API stubs for CodeChecker server.",
"main": "lib",
"homepage": "https://github.com/Ericsson/codechecker",
Expand Down
Binary file modified web/api/py/codechecker_api/dist/codechecker_api.tar.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.70.0'
api_version = '6.71.0'

setup(
name='codechecker_api',
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api_shared/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.70.0'
api_version = '6.71.0'

setup(
name='codechecker_api_shared',
Expand Down
9 changes: 8 additions & 1 deletion web/api/report_server.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -607,8 +607,15 @@ service codeCheckerDBAccess {
i64 storeFilterPreset(1: FilterPreset preset)
throws (1: codechecker_api_shared.RequestFailed requestError);

// Returns: the id of the renamed preset
// Throws an error in case there is no preset with the given id
// PERMISSION: PRODUCT_ADMIN
i64 renameFilterPreset(1: i64 id
2: string name)
throws (1: codechecker_api_shared.RequestFailed requestError);

// Returns the "FilterPreset" identified by id
// Throws and error in case there is no preset with the given id
// Throws an error in case there is no preset with the given id
// PERMISSION: PRODUCT_VIEW
FilterPreset getFilterPreset(1: i64 id)
throws (1: codechecker_api_shared.RequestFailed requestError);
Expand Down
37 changes: 28 additions & 9 deletions web/client/codechecker_client/cli/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1588,15 +1588,6 @@ def __register_delete(parser):
subcommands = parser.add_subparsers(title='available actions')

# Create handlers for individual subcommands.
list_presets = subcommands.add_parser(
'list',
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description="List all filter presets available on the server.",
help="List all filter presets.")
list_presets.set_defaults(func=filter_preset_client.handle_list_presets)
__add_common_arguments(list_presets,
output_formats=DEFAULT_OUTPUT_FORMATS)

new_preset = subcommands.add_parser(
'new',
formatter_class=arg.RawDescriptionDefaultHelpFormatter,
Expand All @@ -1606,6 +1597,34 @@ def __register_delete(parser):
new_preset.set_defaults(func=filter_preset_client.handle_new_preset)
__add_common_arguments(new_preset)

rename_preset = subcommands.add_parser(
'rename',
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description="Rename an existing filter preset.",
help="Rename an existing filter preset.")
rename_preset.set_defaults(func=filter_preset_client.handle_rename_preset)
rename_preset.add_argument(
'--preset-id',
type=int,
required=True,
help="ID of the filter preset to rename.")
rename_preset.add_argument(
'--new-name',
type=str,
required=True,
help="New name for the filter preset.")
__add_common_arguments(rename_preset,
output_formats=DEFAULT_OUTPUT_FORMATS)

list_presets = subcommands.add_parser(
'list',
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description="List all filter presets available on the server.",
help="List all filter presets.")
list_presets.set_defaults(func=filter_preset_client.handle_list_presets)
__add_common_arguments(list_presets,
output_formats=DEFAULT_OUTPUT_FORMATS)

delete_preset = subcommands.add_parser(
'delete',
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
Expand Down
17 changes: 17 additions & 0 deletions web/client/codechecker_client/filter_preset_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,23 @@ def handle_new_preset(args):
sys.exit(1)


def handle_rename_preset(args):
"""
Handler for renaming a filter preset.
"""
init_logger(args.verbose if 'verbose' in args else None)

client = setup_client(args.product_url)

try:
client.renameFilterPreset(args.preset_id, args.new_name)
LOG.info("Filter preset (ID: %d) renamed to '%s'.",
args.preset_id, args.new_name)
except Exception as e:
LOG.error("An error occurred while renaming the filter preset: %s", e)
sys.exit(1)


def handle_list_presets(args):
"""
Handler for listing all filter presets.
Expand Down
4 changes: 4 additions & 0 deletions web/client/codechecker_client/helpers/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ def removeSourceComponent(self, name):
def storeFilterPreset(self, preset):
pass

@thrift_client_call
def renameFilterPreset(self, id, name):
pass

@thrift_client_call
def getFilterPreset(self, id):
pass
Expand Down
2 changes: 1 addition & 1 deletion web/codechecker_web/shared/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# The newest supported minor version (value) for each supported major version
# (key) in this particular build.
SUPPORTED_VERSIONS = {
6: 70
6: 71
}

# Used by the client to automatically identify the latest major and minor
Expand Down
55 changes: 55 additions & 0 deletions web/server/codechecker_server/api/report_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,61 @@ def storeFilterPreset(self, filterpreset):
codechecker_api_shared.ttypes.ErrorCode.DATABASE,
"CodeChecker could not store the filter preset: " + str(ex))

@exc_to_thrift_reqfail
@timeit
def renameFilterPreset(self, preset_id: int, name: str):
"""
Rename a filter preset.
Returns the ID of the renamed preset.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are supplying the preset_id which you want to rename, it is not much information to return it at the end too. I'd return a success instead like a 0 and raise (as currently implemented) if there was any error during. What was the motivation behind returning the preset_id?

Raises an error if id/name is empty or if
a preset with the new name already exists.
"""
self.__require_admin()
try:
with DBSession(self._Session) as session:
if not name or not name.strip():
raise codechecker_api_shared.ttypes.RequestFailed(
codechecker_api_shared.ttypes.ErrorCode.DATABASE,
"Preset name cannot be empty!")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either use "xyz cannot be empty" or "Invalid xyz" but choose one and stick with it. I'd use "Preset name cannot be empty" and "Preset ID cannot be empty" since this error is thrown because a required argument was left out and so it cannot be invalid if it is empty.


if not preset_id:
raise codechecker_api_shared.ttypes.RequestFailed(
codechecker_api_shared.ttypes.ErrorCode.DATABASE,
"Invalid preset ID!")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add an empty line between validation and the actual query of the filter preset for better readability.

preset_entry = session.query(FilterPreset).filter(
FilterPreset.id == preset_id
).one_or_none()

if not preset_entry:
raise codechecker_api_shared.ttypes.RequestFailed(
codechecker_api_shared.ttypes.ErrorCode.DATABASE,
f"No filter preset found with id {preset_id}!")

existing = session.query(FilterPreset).filter(
FilterPreset.preset_name == name
).one_or_none()

if existing and existing.id != preset_id:
raise codechecker_api_shared.ttypes.RequestFailed(
codechecker_api_shared.ttypes.ErrorCode.DATABASE,
f"A filter preset with name "
f"'{name}' already exists!")

LOG.info("Renaming filter preset { id: %d, name: %s } "
"with name: '%s' ",
preset_entry.id, preset_entry.preset_name,
name)

preset_entry.preset_name = name
session.commit()
return preset_entry.id

except Exception as ex:
session.rollback()
raise codechecker_api_shared.ttypes.RequestFailed(
codechecker_api_shared.ttypes.ErrorCode.DATABASE,
"CodeChecker could not rename filter preset: " + str(ex))

@exc_to_thrift_reqfail
@timeit
def deleteFilterPreset(self, preset_id):
Expand Down
8 changes: 4 additions & 4 deletions web/server/vue-cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/server/vue-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@mdi/font": "^6.5.95",
"chart.js": "^4.0.0",
"chartjs-plugin-datalabels": "^2.0.0",
"codechecker-api": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.70.0.tgz",
"codechecker-api": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.71.0.tgz",
"codemirror": "^6.0.2",
"date-fns": "^2.28.0",
"dompurify": "^3.3.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,17 @@
<v-btn
color="primary"
:disabled="!presetName"
@click="saveCurrentFilter(saveMode)"
@click="saveMode !== 'rename'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd move this logic to the function "saveCurrentFilter()" instead. Also it could be renamed to savePreset and it could handle saving and renaming too.

? saveCurrentFilter(saveMode)
: renameFilterPreset()"
>
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<div>
<div
<div
class="mt-2 mb-2 d-flex align-center justify-space-between w-100 p-1"
>
<ClearAllFilters
Expand Down Expand Up @@ -103,6 +105,19 @@
Create Preset
</v-btn>
</div>
<div
v-if="canSeeActions && !presetMenuRef?.isModified
&& presetMenuRef?.activePresetId"
class="d-flex flex-column mb-2 mt-2"
>
<v-btn
color="primary"
class="mb-2"
@click="renamePresetDialog"
>
Rename
</v-btn>
</div>
<div
v-if="canSeeActions && presetMenuRef?.isModified"
class="d-flex flex-column mb-2 mt-2"
Expand Down Expand Up @@ -497,13 +512,14 @@ const saveDialogTitle = computed(() => {
create: "Create new preset",
override: "Override existing preset",
createNew: "Save as new preset",
rename: "Rename the preset"
};
return titles[saveMode.value] || "Save filter preset";
});

watch(() => props.refreshFilter, state => {
if (!state) return;

initByUrl();
emit("set-refresh-filter-state", false);
});
Expand Down Expand Up @@ -685,6 +701,30 @@ function saveCurrentFilter(mode) {
);
}

function renameFilterPreset() {
const preset_id = presetMenuRef.value?.activePresetId;
const new_name = presetName.value;
new Promise(
resolve => {
ccService.getClient().renameFilterPreset(preset_id, new_name,
handleThriftError(result => {
resolve(result);
})
);
})
.then(
result => {
savePresetDialogOpen.value = false;
presetName.value = "";
presetMenuRef.value?.selectPresetAfterSave(result);
}
).catch(
err => {
handleThriftError("FAILURE", err);
}
);
}

function overridePreset() {
saveMode.value = "override";
savePresetDialogOpen.value = true;
Expand All @@ -701,6 +741,10 @@ function createPreset() {
savePresetDialogOpen.value = true;
}

function renamePresetDialog() {
saveMode.value = "rename";
savePresetDialogOpen.value = true;
}
/*function deletePreset(preset_id) {
new Promise(resolve => {
ccService.getClient().deleteFilterPreset(preset_id,
Expand Down
Loading
Loading