Skip to content
Merged
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
6 changes: 4 additions & 2 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"ignorePatterns": ["nuxt.config.ts", "*_typed_schemas.*"],
"ignorePatterns": ["nuxt.config.ts", "*_typed_schemas.*", "oxlint/**"],
"jsPlugins": ["./oxlint/ternary_primitive_only.mjs"],
"categories": {
"correctness": "error",
"suspicious": "error",
Expand Down Expand Up @@ -40,7 +41,7 @@
"ignoreArrayIndexes": true
}
],
"eslint/no-ternary": "off", // A utiliser pour des opérations simples
"eslint/no-ternary": "off", // A utiliser pour des opérations simples (see local/ternary-primitive-only)
"eslint/no-undefined": "off", // Conflict with unicorn/no-typeof-undefined which prefers direct undefined comparison
"eslint/no-void": "off", // Conflicts with typescript/no-floating-promises, whose fix for fire-and-forget promises is the void operator
"eslint/no-underscore-dangle": [
Expand All @@ -67,6 +68,7 @@
"import/no-nodejs-modules": "off",
"import/prefer-default-export": "off",
"import/unambiguous": "off",
"local/ternary-primitive-only": "error",
"max-lines": [
"error",
{
Expand Down
18 changes: 14 additions & 4 deletions app/components/ClippingPlanes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ const slices = ref<{ id: number; axis: SliceAxis; index: number }[]>([
{ id: newItemId(), axis: DEFAULT_SLICE_AXIS, index: 0 },
]);
const sliceMaxIndices = ref<[number, number, number]>([0, 0, 0]);
const targetIds = computed<string[]>(() =>
targetAllVisible.value ? allItems.value.map((item) => item.id) : selectedDatasetIds.value,
);
const targetIds = computed<string[]>(() => {
if (targetAllVisible.value) {
return allItems.value.map((item) => item.id);
}
return selectedDatasetIds.value;
});
const isAllGrid = computed<boolean>(() => areAllGrids(allItems.value, targetIds.value));
const isSliceActive = computed<boolean>(() => isAllGrid.value && sliceEnabled.value);
const availableDatasets = computed<{ title: string; value: string }[]>(() =>
Expand Down Expand Up @@ -97,6 +100,13 @@ async function applyClippingPlanes(): Promise<void> {
}
}

function getSlicesPayload(isActive: boolean): { axis: SliceAxis; index: number }[] {
if (!isActive) {
return [];
}
return slices.value.map(({ axis, index }) => ({ axis, index }));
}

async function sendSlices(): Promise<void> {
if (!isAllGrid.value && !areSlicesApplied) {
return;
Expand All @@ -106,7 +116,7 @@ async function sendSlices(): Promise<void> {
if (targetIds.value.length > 0) {
const maxIndices = await hybridViewerStore.setSlice(
targetIds.value,
isActive ? slices.value.map(({ axis, index }) => ({ axis, index })) : [],
getSlicesPayload(isActive),
);
if (isAllGrid.value) {
sliceMaxIndices.value = maxIndices;
Expand Down
26 changes: 18 additions & 8 deletions app/components/DragAndDrop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ const {
// oxlint-disable-next-line vue/max-props
} = defineProps<Props>();

const displayed_texts = computed<DragAndDropTexts>(() =>
directory
? { ...texts, idle: "Click or drag and drop a folder", drop: "Drop the folder here" }
: texts,
);
const displayed_texts = computed<DragAndDropTexts>(() => {
if (directory) {
return { ...texts, idle: "Click or drag and drop a folder", drop: "Drop the folder here" };
}
return texts;
});

const emit = defineEmits<{
"files-selected": [files: UploadFile[]];
Expand All @@ -57,6 +58,13 @@ const fileInput = ref<HTMLInputElement | undefined>(undefined);

const WILDCARD_SUFFIX_LENGTH = 2;

function getErrorMessage(error: unknown): string {
if (error instanceof Error) {
return error.message;
}
return String(error);
}

function isFileAccepted(file: File, acceptValue: string | string[] | undefined): boolean {
const fileName = (file.name || "").toLowerCase();
const fileType = (file.type || "").toLowerCase();
Expand Down Expand Up @@ -160,16 +168,18 @@ async function emitDroppedEntries(entries: FileSystemEntry[]): Promise<void> {
entries.map(async (entry) => {
const files = await filesFromEntry(entry, entry.name);
// Files inside a dropped folder are all needed: never filtered out.
return entry.isDirectory ? files : files.filter((file) => isFileAccepted(file, accept));
if (entry.isDirectory) {
return files;
}
return files.filter((file) => isFileAccepted(file, accept));
}),
);
const files = groups.flat();
if (files.length > 0) {
emit("files-selected", files);
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
emit("folder-read-error", message);
emit("folder-read-error", getErrorMessage(error));
}
}

Expand Down
15 changes: 9 additions & 6 deletions app/components/FileSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ const toggle_loading = useToggle(loading);

function files_uploaded_event(value: unknown[]): void {
if (value.length > 0) {
emit(
"update_values",
timeSeries
? { files: value, autoUpload: false, time_series: time_series.value }
: { files: value, autoUpload: false },
);
if (timeSeries) {
emit("update_values", {
files: value,
autoUpload: false,
time_series: time_series.value,
});
} else {
emit("update_values", { files: value, autoUpload: false });
}
emit("increment_step");
}
}
Expand Down
10 changes: 8 additions & 2 deletions app/components/HybridViewerTooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ function capitalize(val: string): string {

const fieldTypeLabel = computed<string>(() => {
const fieldType = hybridViewerStore.hoverData?.fieldType;
return typeof fieldType === "string" ? capitalize(fieldType.toLowerCase()) : "";
if (typeof fieldType !== "string") {
return "";
}
return capitalize(fieldType.toLowerCase());
});

const coordinates = computed<number[] | undefined>(() => {
Expand All @@ -114,7 +117,10 @@ function formatAttributeValue(val: unknown): string {
return `[ ${formattedValues.join(", ")} ]`;
}
if (typeof val === "number") {
return Number.isInteger(val) ? String(val) : Number(val).toFixed(4);
if (Number.isInteger(val)) {
return String(val);
}
return Number(val).toFixed(4);
}
return val;
}
Expand Down
16 changes: 10 additions & 6 deletions app/components/MissingFilesSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ const mandatory_files = ref<string[]>([]);
const additional_files = ref<string[]>([]);
const missing_by_file = ref<FileMissingFiles[]>([]);
// Files left out at the data type step are not checked
const checked_filenames = computed(() =>
timeSeries ? filenames : filenames.filter((filename) => filename in geodeObjectTypes),
);
const checked_filenames = computed(() => {
if (timeSeries) {
return filenames;
}
return filenames.filter((filename) => filename in geodeObjectTypes);
});
// Files whose mandatory files are missing are skipped when the step is skipped
const files_without_mandatory = computed(() =>
checked_filenames.value.filter(
Expand Down Expand Up @@ -160,9 +163,10 @@ async function upload_missing_from(
}
const found = expected.flatMap((expected_path, index) => {
const file = folder_files[match.indices[index] ?? -1];
return file && !uploaded.includes(file)
? [Object.assign(file, { relativePath: expected_path })]
: [];
if (file && !uploaded.includes(file)) {
return [Object.assign(file, { relativePath: expected_path })];
}
return [];
});
if (found.length === 0) {
useFeedbackStore().add_warning(`The selected folder does not contain: ${expected.join(", ")}`);
Expand Down
9 changes: 6 additions & 3 deletions app/components/ObjectSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,12 @@ function resolvePerFile(allowedObjectsList: readonly AllowedObjectMap[]): boolea
}
const pending = loadable.filter((file) => file.selectedGeodeObject === undefined);
resolvedTypes.value = Object.fromEntries(
loadable.flatMap((file) =>
file.selectedGeodeObject === undefined ? [] : [[file.filename, file.selectedGeodeObject]],
),
loadable.flatMap((file) => {
if (file.selectedGeodeObject === undefined) {
return [];
}
return [[file.filename, file.selectedGeodeObject]];
}),
);
pendingFilenames.value = pending.map((file) => file.filename);
skippedFiles.value = files
Expand Down
11 changes: 9 additions & 2 deletions app/components/Screenshot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ interface Props {

const { width = DEFAULT_PANEL_WIDTH, escapeFunction = undefined } = defineProps<Props>();

function getErrorMessage(error: unknown): string {
if (error instanceof Error) {
return error.message;
}
return String(error);
}

const output_extensions =
viewer_schemas.opengeodeweb_viewer.viewer.take_screenshot.properties.output_extension.enum;
const filename = ref<string>("");
Expand Down Expand Up @@ -64,7 +71,7 @@ async function deliverScreenshot(blob: Blob | Uint8Array, current_filename: stri
await copy([new ClipboardItem({ "image/png": pngBlob })]);
feedbackStore.add_success("Screenshot copied to clipboard");
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
const message = getErrorMessage(error);
feedbackStore.add_error(
0,
"",
Expand Down Expand Up @@ -138,7 +145,7 @@ async function takeUiScreenshot(current_filename: string): Promise<void> {
const blob = await captureTab(mime_type);
await deliverScreenshot(blob, current_filename);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
const message = getErrorMessage(error);
feedbackStore.add_error(0, "", "Screenshot Error", `Failed to capture the page: ${message}`);
}
}
Expand Down
6 changes: 5 additions & 1 deletion app/components/ThresholdFilter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,11 @@ watch(selectedDatasetId, async (id, previousId) => {
await hybridViewerStore.setThreshold([previousId]);
}
selectedSourceIndex.value = undefined;
sources.value = id ? await fetchSources(id) : [];
if (id) {
sources.value = await fetchSources(id);
} else {
sources.value = [];
}
});

watch(selectedSourceIndex, async (index) => {
Expand Down
12 changes: 7 additions & 5 deletions app/components/Viewer/Generic/Model/BlocksOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ const referenceBlockId = computed<string | undefined>(() =>
collections ? targetBlockIds[0] : undefined,
);

const blockComponentIds = computed<string[]>(() => (blockId === undefined ? [] : [blockId]));
const blockComponentIds = computed<string[]>(() => (blockId !== undefined && [blockId]) || []);

// Visibility
const blocksVisibility = computed<boolean>({
get: () =>
collections
? targetBlockIds.every((id) => dataStyleStore.modelBlockVisibility(modelId, id))
: dataStyleStore.modelComponentTypeVisibility(modelId, "Block"),
get: () => {
if (collections) {
return targetBlockIds.every((id) => dataStyleStore.modelBlockVisibility(modelId, id));
}
return dataStyleStore.modelComponentTypeVisibility(modelId, "Block");
},
set: async (newValue) => {
await dataStyleStore.setModelBlocksVisibility(modelId, targetBlockIds, newValue);
hybridViewerStore.remoteRender();
Expand Down
12 changes: 7 additions & 5 deletions app/components/Viewer/Generic/Model/CornersOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ const referenceCornerId = computed<string | undefined>(() =>
collections ? targetCornerIds[0] : undefined,
);

const cornerComponentIds = computed<string[]>(() => (cornerId === undefined ? [] : [cornerId]));
const cornerComponentIds = computed<string[]>(() => (cornerId !== undefined && [cornerId]) || []);

// Visibility
const cornersVisibility = computed<boolean>({
get: () =>
collections
? targetCornerIds.every((id) => dataStyleStore.modelCornerVisibility(modelId, id))
: dataStyleStore.modelComponentTypeVisibility(modelId, "Corner"),
get: () => {
if (collections) {
return targetCornerIds.every((id) => dataStyleStore.modelCornerVisibility(modelId, id));
}
return dataStyleStore.modelComponentTypeVisibility(modelId, "Corner");
},
set: async (newValue) => {
await dataStyleStore.setModelCornersVisibility(modelId, targetCornerIds, newValue);
hybridViewerStore.remoteRender();
Expand Down
16 changes: 8 additions & 8 deletions app/components/Viewer/Generic/Model/LinesOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ const {
const dataStyleStore = useDataStyleStore();
const hybridViewerStore = useHybridViewerStore();

const referenceLineId = computed<string | undefined>(() =>
collections ? targetLineIds[0] : undefined,
);
const referenceLineId = computed(() => (collections ? targetLineIds[0] : undefined));

const lineComponentIds = computed<string[]>(() => (lineId === undefined ? [] : [lineId]));
const lineComponentIds = computed<string[]>(() => (lineId !== undefined && [lineId]) || []);

// Visibility
const linesVisibility = computed<boolean>({
get: () =>
collections
? targetLineIds.every((id) => dataStyleStore.modelLineVisibility(modelId, id))
: dataStyleStore.modelComponentTypeVisibility(modelId, "Line"),
get: () => {
if (collections) {
return targetLineIds.every((id) => dataStyleStore.modelLineVisibility(modelId, id));
}
return dataStyleStore.modelComponentTypeVisibility(modelId, "Line");
},
set: async (newValue) => {
await dataStyleStore.setModelLinesVisibility(modelId, targetLineIds, newValue);
hybridViewerStore.remoteRender();
Expand Down
22 changes: 12 additions & 10 deletions app/components/Viewer/Generic/Model/ModelEdgesCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,22 @@ watch(
{ immediate: true },
);

const typeTargets = computed(() =>
edgesComponentType.value === undefined
? []
: [{ componentType: edgesComponentType.value, componentIds: targetComponentIds.value }],
);
const typeTargets = computed(() => {
if (edgesComponentType.value === undefined) {
return [];
}
return [{ componentType: edgesComponentType.value, componentIds: targetComponentIds.value }];
});
const typeReferenceId = computed<string | undefined>(() =>
collections.value ? targetComponentIds.value[0] : undefined,
);

const componentTargets = computed(() =>
edgesComponentType.value === undefined || componentId.value === undefined
? []
: [{ componentType: edgesComponentType.value, componentIds: [componentId.value] }],
);
const componentTargets = computed(() => {
if (edgesComponentType.value === undefined || componentId.value === undefined) {
return [];
}
return [{ componentType: edgesComponentType.value, componentIds: [componentId.value] }];
});

const { tabs, activeTab } = useModelTabs({
componentType,
Expand Down
22 changes: 12 additions & 10 deletions app/components/Viewer/Generic/Model/ModelPointsCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,22 @@ watch(
{ immediate: true },
);

const typeTargets = computed(() =>
pointsComponentType.value === undefined
? []
: [{ componentType: pointsComponentType.value, componentIds: targetComponentIds.value }],
);
const typeTargets = computed(() => {
if (pointsComponentType.value === undefined) {
return [];
}
return [{ componentType: pointsComponentType.value, componentIds: targetComponentIds.value }];
});
const typeReferenceId = computed<string | undefined>(() =>
collections.value ? targetComponentIds.value[0] : undefined,
);

const componentTargets = computed(() =>
pointsComponentType.value === undefined || componentId.value === undefined
? []
: [{ componentType: pointsComponentType.value, componentIds: [componentId.value] }],
);
const componentTargets = computed(() => {
if (pointsComponentType.value === undefined || componentId.value === undefined) {
return [];
}
return [{ componentType: pointsComponentType.value, componentIds: [componentId.value] }];
});

const { tabs, activeTab } = useModelTabs({
componentType,
Expand Down
Loading
Loading