Skip to content

Commit 2f5a71f

Browse files
authored
Merge pull request #95 from THM-Graphs/feature/image-url-conditions
Image url conditions
2 parents 367b627 + 1613fe8 commit 2f5a71f

12 files changed

Lines changed: 113 additions & 2 deletions

File tree

nakar-client-web/src-gen/api-client/types.gen.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export type NodeConfigurationDto = {
3030
property: string;
3131
linkTemplate: string;
3232
urlEncode: boolean;
33+
valueRegex: string;
3334
};
3435

3536
export type DatabaseConnectionDto = {
@@ -237,6 +238,7 @@ export type UpdateNodeConfigurationRequestBodyDto = {
237238
property: string;
238239
linkTemplate: string;
239240
urlEncode: boolean;
241+
valueRegex: string;
240242
};
241243

242244
export type UpdateDatabaseConnectionRequestBodyDto = {

nakar-client-web/src/shared/cms/NodeConfigurationEditor.tsx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export function NodeConfigurationEditor(props: {
122122
</Form.Label>
123123
<Form.Control
124124
type="text"
125-
placeholder="https://images.org/{{value}}.png"
125+
placeholder="https://images.org/{{{value}}}.png"
126126
className={"font-monospace"}
127127
value={props.value.linkTemplate}
128128
onChange={(e) => {
@@ -153,6 +153,42 @@ export function NodeConfigurationEditor(props: {
153153
/>
154154
</Form.Group>
155155
</Col>
156+
{props.value.type === "image" && (
157+
<Col>
158+
<Form.Group className="" controlId={`valueRegex_${key}`}>
159+
<Form.Label>
160+
Value Regex{" "}
161+
<OverlayTrigger
162+
overlay={
163+
<Tooltip>
164+
Define a regex expression to filter values.
165+
</Tooltip>
166+
}
167+
>
168+
<i className={"bi bi-info-circle"}></i>
169+
</OverlayTrigger>
170+
</Form.Label>
171+
<Form.Control
172+
type="text"
173+
placeholder=".*\.jpg$"
174+
className={"font-monospace"}
175+
value={props.value.valueRegex}
176+
onChange={(e) => {
177+
props.onChange({
178+
...props.value,
179+
valueRegex: e.target.value,
180+
});
181+
}}
182+
/>
183+
</Form.Group>
184+
<Form.Text className={"small text-muted"}>
185+
Example:{" "}
186+
<code className={"user-select-text code"}>
187+
commons\.wikimedia\.org
188+
</code>
189+
</Form.Text>
190+
</Col>
191+
)}
156192
</Row>
157193
</Stack>
158194
{props.onDelete != null && (

nakar-client-web/src/shared/cms/NodeConfigurationsEditor.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function NodeConfigurationsEditor(props: {
1717
label: "",
1818
linkTemplate: "",
1919
urlEncode: false,
20+
valueRegex: "",
2021
};
2122
props.onChange([...props.value, newNodeConfiguration]);
2223
}, [props.value, props.onChange]);

nakar-server/src/api/node-configuration/content-types/node-configuration/schema.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
"urlEncode": {
3737
"type": "boolean",
3838
"required": false
39+
},
40+
"valueRegex": {
41+
"type": "string"
3942
}
4043
}
4144
}

nakar-server/src/lib/application/AppModule.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { CommonPropertiesController } from '../http/routes/common-properties/Com
2424
import { MonitoringService } from '../monitoring/MonitoringService';
2525
import { MediaService } from '../media/MediaService';
2626
import { EncryptionService } from '../encryption/EncryptionService';
27+
import { IsValidRegex } from '../schema/IsValidRegex';
2728

2829
@Module({
2930
controllers: [
@@ -54,6 +55,7 @@ import { EncryptionService } from '../encryption/EncryptionService';
5455
MonitoringService,
5556
MediaService,
5657
EncryptionService,
58+
IsValidRegex,
5759
],
5860
})
5961
export class AppModule {}

nakar-server/src/lib/database/DatabaseService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,7 @@ export class DatabaseService {
11911191
linkTemplate: newDocument.linkTemplate,
11921192
database: databaseConnection.documentId,
11931193
urlEncode: newDocument.urlEncode,
1194+
valueRegex: newDocument.valueRegex,
11941195
};
11951196

11961197
const updatedDocument: Modules.Documents.Result<'api::node-configuration.node-configuration'> | null =

nakar-server/src/lib/http/routes/database-connection/dto/UpdateNodeConfigurationRequestBodyDto.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { ApiProperty } from '@nestjs/swagger';
22
import { NodeConfigurationTypeDto } from '../../../../schema/dtos/NodeConfigurationTypeDto';
3-
import { IsBoolean, IsEnum, IsNotEmpty, IsString } from 'class-validator';
3+
import {
4+
IsBoolean,
5+
IsEnum,
6+
IsNotEmpty,
7+
IsString,
8+
Validate,
9+
} from 'class-validator';
10+
import { IsValidRegex } from '../../../../schema/IsValidRegex';
411

512
export class UpdateNodeConfigurationRequestBodyDto {
613
@ApiProperty({ type: String })
@@ -27,4 +34,9 @@ export class UpdateNodeConfigurationRequestBodyDto {
2734
@ApiProperty({ type: Boolean })
2835
@IsBoolean()
2936
public urlEncode!: boolean;
37+
38+
@ApiProperty({ type: String })
39+
@IsString()
40+
@Validate(IsValidRegex)
41+
public valueRegex!: string;
3042
}

nakar-server/src/lib/live-canvas/graph/NodeIndex.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,19 @@ export class NodeIndex {
309309
if (value == null) {
310310
continue;
311311
}
312+
313+
// Check regex
314+
const regexToUse: string = nodeConfig.valueRegex?.trim() ?? '';
315+
if (
316+
regexToUse.length > 0 &&
317+
!this._valueMatchesRegex(value, regexToUse)
318+
) {
319+
this._logger.debug(
320+
`Will skip node value for image url, because regex does not match.\nValue: ${value}\nRegex: ${regexToUse}`,
321+
);
322+
continue;
323+
}
324+
312325
const template: HandlebarsTemplateDelegate = Handlebars.compile(
313326
nodeConfig.linkTemplate,
314327
);
@@ -370,4 +383,13 @@ export class NodeIndex {
370383
}
371384
return null;
372385
}
386+
387+
private _valueMatchesRegex(inputString: string, regex: string): boolean {
388+
try {
389+
return new RegExp(regex).test(inputString);
390+
} catch (error: unknown) {
391+
this._logger.error(error);
392+
return false;
393+
}
394+
}
373395
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {
2+
ValidationArguments,
3+
ValidatorConstraint,
4+
ValidatorConstraintInterface,
5+
} from 'class-validator';
6+
7+
@ValidatorConstraint({ name: 'isValidRegex', async: false })
8+
export class IsValidRegex implements ValidatorConstraintInterface {
9+
public validate(value: unknown): boolean {
10+
if (typeof value !== 'string') {
11+
return false;
12+
}
13+
14+
try {
15+
new RegExp(value);
16+
return true;
17+
} catch {
18+
return false;
19+
}
20+
}
21+
22+
public defaultMessage(args: ValidationArguments): string {
23+
return `${args.property} must be a valid regex.`;
24+
}
25+
}

nakar-server/src/lib/schema/SchemaFactoryService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ export class SchemaFactoryService {
106106
property: nodeConfiguration.property ?? '',
107107
linkTemplate: nodeConfiguration.linkTemplate ?? '',
108108
urlEncode: nodeConfiguration.urlEncode ?? false,
109+
valueRegex: nodeConfiguration.valueRegex ?? '',
109110
}),
110111
),
111112
databaseType: match(databaseDBDTO.databaseType)

0 commit comments

Comments
 (0)