Skip to content

Commit 3693f0a

Browse files
Merge pull request #2231 from AletheiaFact/Refactor/generalizing-drawer-forms
Refactor: Unified Dynamic Form for Creation and Edition Flows
2 parents ffebf55 + 5ffa1cc commit 3693f0a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+838
-768
lines changed

public/locales/en/badges.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
{
2-
"nameColumn": "Name",
3-
"descriptionColumn": "Description",
4-
"imageColumn": "Image",
2+
"nameLabel": "Name",
3+
"namePlaceholder": "Enter badge name",
4+
"descriptionLabel": "Description",
5+
"descriptionPlaceholder": "Enter description",
6+
"imageFieldLabel": "Image",
57
"title": "Badges area",
68
"addBadge": "Add badge",
79
"editBadge": "Edit badge",

public/locales/en/namespaces.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
2-
"nameColumn": "Name",
2+
"nameLabel": "Name",
3+
"namePlaceholder":"Namespace name",
34
"title": "Namespaces area",
45
"addNameSpace": "Add namespace",
56
"editNameSpace": "Edit namespace",

public/locales/pt/badges.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
{
2-
"nameColumn": "Nome",
3-
"descriptionColumn": "Descrição",
4-
"imageColumn": "Imagem",
2+
"nameLabel": "Nome",
3+
"namePlaceholder": "Insira o nome da insígnia",
4+
"descriptionLabel": "Descrição",
5+
"descriptionPlaceholder": "Insira a descrição",
6+
"imageFieldLabel": "Imagem",
57
"title": "Área de Insígnias",
68
"addBadge": "Adicionar Insígnia",
79
"editBadge": "Editar Insígnia",

public/locales/pt/claimForm.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"checkboxAcceptTerms": "Eu atesto pessoalmente que toda informação adicionada é confiável.",
2525
"cancelButton": "Cancelar",
2626
"updateButton": "Atualizar",
27-
"saveButton": "Adicionar",
27+
"saveButton": "Salvar",
2828
"contentModelTitle": "Formato",
2929
"selectContentModel": "Que formato de afirmação você quer incluir?",
3030
"Image": "Imagem",

public/locales/pt/namespaces.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
2-
"nameColumn": "Nome",
2+
"nameLabel": "Nome",
3+
"namePlaceholder":"Nome do namespace",
34
"title": "Área de namespaces",
45
"addNameSpace": "Adicionar namespace",
56
"editNameSpace": "Editar namespace",

server/auth/name-space/name-space.controller.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ import { Types } from "mongoose";
2222
import { Roles } from "../../auth/ability/ability.factory";
2323
import { NotificationService } from "../../notifications/notifications.service";
2424
import slugify from "slugify";
25+
import { ConfigService } from "@nestjs/config";
2526

2627
@Controller()
2728
export class NameSpaceController {
2829
constructor(
2930
private nameSpaceService: NameSpaceService,
3031
private usersService: UsersService,
3132
private viewService: ViewService,
32-
private notificationService: NotificationService
33+
private notificationService: NotificationService,
34+
private configService: ConfigService,
3335
) {}
3436

3537
@AdminOnly()
@@ -59,13 +61,14 @@ export class NameSpaceController {
5961
...namespaceBody,
6062
};
6163

62-
newNameSpace.slug = slugify(nameSpace.name, {
64+
newNameSpace.slug = slugify(newNameSpace.name, {
6365
lower: true,
6466
strict: true,
6567
});
6668

6769
newNameSpace.users = await this.updateNameSpaceUsers(
6870
newNameSpace.users,
71+
newNameSpace.slug,
6972
nameSpace.slug
7073
);
7174

@@ -100,25 +103,35 @@ export class NameSpaceController {
100103
const users = await this.usersService.findAll({});
101104
const parsedUrl = parse(req.url, true);
102105

103-
const query = Object.assign(parsedUrl.query, { nameSpaces, users });
106+
const query = Object.assign(
107+
parsedUrl.query,
108+
{
109+
sitekey: this.configService.get<string>("recaptcha_sitekey"),
110+
nameSpaces,
111+
users
112+
}
113+
);
104114

105115
await this.viewService.render(req, res, "/admin-namespaces", query);
106116
}
107117

108-
private async updateNameSpaceUsers(users, key) {
118+
private async updateNameSpaceUsers(users, newKey, oldKey = null) {
109119
const promises = users.map(async (user) => {
110120
const userId = Types.ObjectId(user._id);
111121
const existingUser = await this.usersService.getById(userId);
112122

113-
if (!existingUser.role[key]) {
114-
await this.usersService.updateUser(existingUser._id, {
115-
role: {
116-
...existingUser.role,
117-
[key]: Roles.Regular,
118-
},
119-
});
123+
let updatedRoles = { ...existingUser.role };
124+
125+
if (oldKey && oldKey !== newKey) {
126+
delete updatedRoles[oldKey];
120127
}
121128

129+
updatedRoles[newKey] = Roles.Regular;
130+
131+
await this.usersService.updateUser(existingUser._id, {
132+
role: updatedRoles,
133+
});
134+
122135
return userId;
123136
});
124137

server/badge/badge.controller.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Types } from "mongoose";
2020
import { ApiTags } from "@nestjs/swagger";
2121
import { UtilService } from "../util";
2222
import { AdminOnly } from "../auth/decorators/auth.decorator";
23+
import { ConfigService } from "@nestjs/config";
2324

2425
@Controller(":namespace?")
2526
export class BadgeController {
@@ -28,7 +29,8 @@ export class BadgeController {
2829
private viewService: ViewService,
2930
private imageService: ImageService,
3031
private usersService: UsersService,
31-
private util: UtilService
32+
private util: UtilService,
33+
private configService: ConfigService,
3234
) {}
3335

3436
@AdminOnly()
@@ -152,6 +154,7 @@ export class BadgeController {
152154
badges,
153155
users,
154156
nameSpace: req.params.namespace,
157+
sitekey: this.configService.get<string>("recaptcha_sitekey"),
155158
});
156159

157160
await this.viewService.render(req, res, "/admin-badges", query);

server/verification-request/verification-request.service.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -704,15 +704,7 @@ export class VerificationRequestService {
704704
return src._id;
705705
})
706706
);
707-
708-
updatedVerificationRequestData.source = Array.from(
709-
new Set([
710-
...(verificationRequest.source || []).map((sourceId) =>
711-
sourceId.toString()
712-
),
713-
...newSourceIds.map((id) => id.toString()),
714-
])
715-
).map((id) => Types.ObjectId(id));
707+
updatedVerificationRequestData.source = newSourceIds.map((id) => Types.ObjectId(id));
716708
}
717709

718710
if (
@@ -743,7 +735,8 @@ export class VerificationRequestService {
743735
verificationRequest._id,
744736
updatedVerificationRequestData,
745737
{ new: true, upsert: true }
746-
).populate("source");
738+
).populate("source")
739+
.populate("impactArea");
747740
} catch (error) {
748741
this.logger.error("Failed to update verification request:", error);
749742
throw error;

src/components/Form/DatePickerInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const StyledTextField = styled(TextField)`
4141

4242
const DatePickerInput = (props) => {
4343
const { t } = useTranslation();
44-
const [value, setValue] = useState(null);
44+
const [value, setValue] = useState(props.defaultValue || null);
4545
const [open, setOpen] = useState(false);
4646

4747
return (

src/components/Form/DynamicInput.tsx

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,26 @@ import { VisualEditorContext } from "../Collaborative/VisualEditorProvider";
1010
import AletheiaInput from "../AletheiaInput";
1111
import DatePickerInput from "./DatePickerInput";
1212
import { Checkbox, FormControlLabel } from "@mui/material";
13-
import ReportTypeSelect from "../VerificationRequest/CreateVerificationRequest/ReportTypeSelect";
14-
import ImpactAreaSelect from "../VerificationRequest/CreateVerificationRequest/ImpactAreaSelect";
1513
import colors from "../../styles/colors";
14+
import ReportTypeSelect from "../VerificationRequest/verificationRequestForms/formInputs/ReportTypeSelect";
15+
import ImpactAreaSelect from "../VerificationRequest/verificationRequestForms/formInputs/ImpactAreaSelect";
16+
import InputExtraSourcesList from "../VerificationRequest/verificationRequestForms/formInputs/InputExtraSourcesList";
17+
import { Topic } from "../../types/Topic";
18+
import { SourceType } from "../../types/Source";
19+
import ImageUpload, { UploadFile } from "../ImageUpload";
1620

1721
const VisualEditor = lazy(() => import("../Collaborative/VisualEditor"));
1822

23+
export type UnifiedDefaultValue = Topic | SourceType[] | UploadFile[] | string
24+
1925
interface DynamicInputProps {
2026
fieldName: string;
2127
type: string;
2228
placeholder: string;
23-
value: string | [];
29+
value: UnifiedDefaultValue;
2430
onChange: any;
2531
addInputLabel: string;
26-
defaultValue: string | [];
32+
defaultValue: UnifiedDefaultValue;
2733
"data-cy": string;
2834
extraProps: any;
2935
disabledDate?: any;
@@ -83,6 +89,15 @@ const DynamicInput = (props: DynamicInputProps) => {
8389
white="true"
8490
/>
8591
);
92+
case "sourceList":
93+
return (
94+
<InputExtraSourcesList
95+
sources={props.value}
96+
onChange={props.onChange}
97+
disabled={props.disabled}
98+
placeholder={props.placeholder}
99+
/>
100+
);
86101
case "select":
87102
return (
88103
<ClaimReviewSelect
@@ -98,14 +113,23 @@ const DynamicInput = (props: DynamicInputProps) => {
98113
defaultValue={props.defaultValue}
99114
onChange={(value) => props.onChange(value)}
100115
placeholder={t(props.placeholder)}
101-
116+
isDisabled={props.disabled}
102117
/>
103118
);
104119
case "selectImpactArea":
105120
return (
106121
<ImpactAreaSelect
122+
defaultValue={props.defaultValue}
107123
onChange={(value) => props.onChange(value)}
108124
placeholder={t(props.placeholder)}
125+
isDisabled={props.disabled}
126+
/>
127+
);
128+
case "imageUpload":
129+
return (
130+
<ImageUpload
131+
onChange={(value) => props.onChange(value)}
132+
defaultFileList={props.defaultValue}
109133
/>
110134
);
111135
case "textbox":
@@ -141,6 +165,7 @@ const DynamicInput = (props: DynamicInputProps) => {
141165
case "date":
142166
return (
143167
<DatePickerInput
168+
defaultValue={props.defaultValue}
144169
placeholder={t(props.placeholder)}
145170
onChange={(value) => props.onChange(value)}
146171
data-cy={"testSelectDate"}

0 commit comments

Comments
 (0)