diff --git a/src/backend/app/auth/roles.py b/src/backend/app/auth/roles.py index c881b3214b..96278f62be 100644 --- a/src/backend/app/auth/roles.py +++ b/src/backend/app/auth/roles.py @@ -69,7 +69,7 @@ async def org_admin( db: Session = Depends(get_db), user_data: AuthUser = Depends(login_required), ) -> AuthUser: - """Organization admin with full permission for projects in an organization.""" + """Organisation admin with full permission for projects in an organisation.""" if project and org_id: log.error("Both org_id and project_id cannot be passed at the same time") raise HTTPException( @@ -89,10 +89,10 @@ async def org_admin( ) if not org_admin: - log.error(f"User ID {user_id} is not an admin for organization {org_id}") + log.error(f"User ID {user_id} is not an admin for organisation {org_id}") raise HTTPException( status_code=HTTPStatus.FORBIDDEN, - detail="User is not organization admin", + detail="User is not organisation admin", ) return user_data diff --git a/src/backend/app/main.py b/src/backend/app/main.py index 0c8ac7cd77..071106caed 100644 --- a/src/backend/app/main.py +++ b/src/backend/app/main.py @@ -34,10 +34,10 @@ from app.central import central_routes from app.config import settings from app.db.database import get_db -from app.organization import organization_routes +from app.organisations import organisation_routes from app.projects import project_routes from app.projects.project_crud import read_xlsforms -from app.submission import submission_routes +from app.submissions import submission_routes from app.tasks import tasks_routes from app.users import user_routes @@ -95,7 +95,7 @@ def get_application() -> FastAPI: _app.include_router(central_routes.router) _app.include_router(auth_routes.router) _app.include_router(submission_routes.router) - _app.include_router(organization_routes.router) + _app.include_router(organisation_routes.router) return _app diff --git a/src/backend/app/organization/__init__.py b/src/backend/app/organisations/__init__.py similarity index 100% rename from src/backend/app/organization/__init__.py rename to src/backend/app/organisations/__init__.py diff --git a/src/backend/app/organization/organization_crud.py b/src/backend/app/organisations/organisation_crud.py similarity index 65% rename from src/backend/app/organization/organization_crud.py rename to src/backend/app/organisations/organisation_crud.py index cfbedf5815..a058a70514 100644 --- a/src/backend/app/organization/organization_crud.py +++ b/src/backend/app/organisations/organisation_crud.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with FMTM. If not, see . # -"""Logic for organization management.""" +"""Logic for organisation management.""" from io import BytesIO @@ -27,10 +27,10 @@ from app.config import settings from app.db import db_models from app.models.enums import HTTPStatus -from app.organization.organization_deps import ( - get_organization_by_name, +from app.organisations.organisation_deps import ( + get_organisation_by_name, ) -from app.organization.organization_schemas import OrganisationEdit, OrganisationIn +from app.organisations.organisation_schemas import OrganisationEdit, OrganisationIn from app.s3 import add_obj_to_bucket @@ -50,7 +50,7 @@ async def upload_logo_to_s3( so it should not matter if a .jpg is renamed .png. Args: - db_org(db_models.DbOrganisation): The organization database object. + db_org(db_models.DbOrganisation): The organisation database object. logo_file(UploadFile): The logo image uploaded to FastAPI. Returns: @@ -73,65 +73,65 @@ async def upload_logo_to_s3( return logo_url -async def create_organization( +async def create_organisation( db: Session, org_model: OrganisationIn, logo: UploadFile(None) ) -> db_models.DbOrganisation: - """Creates a new organization with the given name, description, url, type, and logo. + """Creates a new organisation with the given name, description, url, type, and logo. Saves the logo file S3 bucket under /{org_id}/logo.png. Args: db (Session): database session - org_model (OrganisationIn): Pydantic model for organization input. - logo (UploadFile, optional): logo file of the organization. + org_model (OrganisationIn): Pydantic model for organisation input. + logo (UploadFile, optional): logo file of the organisation. Defaults to File(...). Returns: - DbOrganization: SQLAlchemy Organization model. + DbOrganisation: SQLAlchemy Organisation model. """ - if await get_organization_by_name(db, org_name=org_model.name): + if await get_organisation_by_name(db, org_name=org_model.name): raise HTTPException( status_code=HTTPStatus.CONFLICT, - detail=f"Organization already exists with the name {org_model.name}", + detail=f"Organisation already exists with the name {org_model.name}", ) # Required to check if exists on error - db_organization = None + db_organisation = None try: - # Create new organization without logo set - db_organization = db_models.DbOrganisation(**org_model.dict()) + # Create new organisation without logo set + db_organisation = db_models.DbOrganisation(**org_model.dict()) - db.add(db_organization) + db.add(db_organisation) db.commit() # Refresh to get the assigned org id - db.refresh(db_organization) + db.refresh(db_organisation) # Update the logo field in the database with the correct path if logo: - db_organization.logo = await upload_logo_to_s3(db_organization, logo) + db_organisation.logo = await upload_logo_to_s3(db_organisation, logo) db.commit() except Exception as e: log.exception(e) - log.debug("Rolling back changes to db organization") + log.debug("Rolling back changes to db organisation") # Rollback any changes db.rollback() - # Delete the failed organization entry - if db_organization: - log.debug(f"Deleting created organisation ID {db_organization.id}") - db.delete(db_organization) + # Delete the failed organisation entry + if db_organisation: + log.debug(f"Deleting created organisation ID {db_organisation.id}") + db.delete(db_organisation) db.commit() raise HTTPException( - status_code=400, detail=f"Error creating organization: {e}" + status_code=400, detail=f"Error creating organisation: {e}" ) from e - return db_organization + return db_organisation -async def update_organization( +async def update_organisation( db: Session, - organization: db_models.DbOrganisation, + organisation: db_models.DbOrganisation, values: OrganisationEdit, logo: UploadFile(None), ) -> db_models.DbOrganisation: @@ -139,50 +139,50 @@ async def update_organization( Args: db (Session): database session - organization (DbOrganisation): Editing database model. - values (OrganisationEdit): Pydantic model for organization edit. - logo (UploadFile, optional): logo file of the organization. + organisation (DbOrganisation): Editing database model. + values (OrganisationEdit): Pydantic model for organisation edit. + logo (UploadFile, optional): logo file of the organisation. Defaults to File(...). Returns: - DbOrganization: SQLAlchemy Organization model. + DbOrganisation: SQLAlchemy Organisation model. """ if not (updated_fields := values.dict(exclude_none=True)): raise HTTPException( status_code=HTTPStatus.UNPROCESSABLE_ENTITY, - detail=f"No values were provided to update organization {organization.id}", + detail=f"No values were provided to update organisation {organisation.id}", ) update_cmd = ( update(db_models.DbOrganisation) - .where(db_models.DbOrganisation.id == organization.id) + .where(db_models.DbOrganisation.id == organisation.id) .values(**updated_fields) ) db.execute(update_cmd) if logo: - organization.logo = await upload_logo_to_s3(organization, logo) + organisation.logo = await upload_logo_to_s3(organisation, logo) db.commit() - db.refresh(organization) + db.refresh(organisation) - return organization + return organisation -async def delete_organization( +async def delete_organisation( db: Session, - organization: db_models.DbOrganisation, + organisation: db_models.DbOrganisation, ) -> Response: """Delete an existing organisation database entry. Args: db (Session): database session - organization (DbOrganisation): Database model to delete. + organisation (DbOrganisation): Database model to delete. Returns: bool: If deletion was successful. """ - db.delete(organization) + db.delete(organisation) db.commit() return Response(status_code=HTTPStatus.NO_CONTENT) diff --git a/src/backend/app/organization/organization_deps.py b/src/backend/app/organisations/organisation_deps.py similarity index 68% rename from src/backend/app/organization/organization_deps.py rename to src/backend/app/organisations/organisation_deps.py index 058f8e7b3d..b4aad5f41b 100644 --- a/src/backend/app/organization/organization_deps.py +++ b/src/backend/app/organisations/organisation_deps.py @@ -16,7 +16,7 @@ # along with FMTM. If not, see . # -"""Organization dependencies for use in Depends.""" +"""Organisation dependencies for use in Depends.""" from typing import Union @@ -31,15 +31,15 @@ from app.models.enums import HTTPStatus -async def get_organization_by_name(db: Session, org_name: str) -> DbOrganisation: - """Get an organization from the db by name. +async def get_organisation_by_name(db: Session, org_name: str) -> DbOrganisation: + """Get an organisation from the db by name. Args: db (Session): database session - org_name (int): id of the organization + org_name (int): id of the organisation Returns: - DbOrganisation: organization with the given id + DbOrganisation: organisation with the given id """ return ( db.query(DbOrganisation) @@ -49,14 +49,14 @@ async def get_organization_by_name(db: Session, org_name: str) -> DbOrganisation async def get_organisation_by_id(db: Session, org_id: int) -> DbOrganisation: - """Get an organization from the db by id. + """Get an organisation from the db by id. Args: db (Session): database session - org_id (int): id of the organization + org_id (int): id of the organisation Returns: - DbOrganisation: organization with the given id + DbOrganisation: organisation with the given id """ return db.query(DbOrganisation).filter(DbOrganisation.id == org_id).first() @@ -65,7 +65,7 @@ async def org_exists( org_id: Union[str, int], db: Session = Depends(get_db), ) -> DbOrganisation: - """Check if organization name exists, else error. + """Check if organisation name exists, else error. The org_id can also be an org name. """ @@ -75,18 +75,18 @@ async def org_exists( pass if isinstance(org_id, int): - log.debug(f"Getting organization by id: {org_id}") - db_organization = await get_organisation_by_id(db, org_id) + log.debug(f"Getting organisation by id: {org_id}") + db_organisation = await get_organisation_by_id(db, org_id) if isinstance(org_id, str): - log.debug(f"Getting organization by name: {org_id}") - db_organization = await get_organization_by_name(db, org_id) + log.debug(f"Getting organisation by name: {org_id}") + db_organisation = await get_organisation_by_name(db, org_id) - if not db_organization: + if not db_organisation: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, - detail=f"Organization {org_id} does not exist", + detail=f"Organisation {org_id} does not exist", ) - log.debug(f"Organization match: {db_organization}") - return db_organization + log.debug(f"Organisation match: {db_organisation}") + return db_organisation diff --git a/src/backend/app/organisations/organisation_routes.py b/src/backend/app/organisations/organisation_routes.py new file mode 100644 index 0000000000..b81dc8d763 --- /dev/null +++ b/src/backend/app/organisations/organisation_routes.py @@ -0,0 +1,87 @@ +# Copyright (c) 2022, 2023 Humanitarian OpenStreetMap Team +# +# This file is part of FMTM. +# +# FMTM is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# FMTM is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with FMTM. If not, see . +# +"""Routes for organisation management.""" + +from fastapi import ( + APIRouter, + Depends, + File, + UploadFile, +) +from sqlalchemy.orm import Session + +from app.db import database +from app.db.db_models import DbOrganisation +from app.organisations import organisation_crud, organisation_schemas +from app.organisations.organisation_deps import org_exists + +router = APIRouter( + prefix="/organisation", + tags=["organisation"], + dependencies=[Depends(database.get_db)], + responses={404: {"description": "Not found"}}, +) + + +@router.get("/", response_model=list[organisation_schemas.OrganisationOut]) +def get_organisations( + db: Session = Depends(database.get_db), +) -> list[organisation_schemas.OrganisationOut]: + """Get a list of all organisations.""" + return organisation_crud.get_organisations(db) + + +@router.get("/{org_id}", response_model=organisation_schemas.OrganisationOut) +async def get_organisation_detail( + organisation: DbOrganisation = Depends(org_exists), + db: Session = Depends(database.get_db), +): + """Get a specific organisation by id or name.""" + return organisation + + +@router.post("/", response_model=organisation_schemas.OrganisationOut) +async def create_organisation( + org: organisation_schemas.OrganisationIn = Depends(), + logo: UploadFile = File(None), + db: Session = Depends(database.get_db), +) -> organisation_schemas.OrganisationOut: + """Create an organisation with the given details.""" + return await organisation_crud.create_organisation(db, org, logo) + + +@router.patch("/{org_id}/", response_model=organisation_schemas.OrganisationOut) +async def update_organisation( + new_values: organisation_schemas.OrganisationEdit = Depends(), + logo: UploadFile = File(None), + organisation: DbOrganisation = Depends(org_exists), + db: Session = Depends(database.get_db), +): + """Partial update for an existing organisation.""" + return await organisation_crud.update_organisation( + db, organisation, new_values, logo + ) + + +@router.delete("/{org_id}") +async def delete_organisations( + organisation: DbOrganisation = Depends(org_exists), + db: Session = Depends(database.get_db), +): + """Delete an organisation.""" + return await organisation_crud.delete_organisation(db, organisation) diff --git a/src/backend/app/organization/organization_schemas.py b/src/backend/app/organisations/organisation_schemas.py similarity index 86% rename from src/backend/app/organization/organization_schemas.py rename to src/backend/app/organisations/organisation_schemas.py index 62b5846241..26f76af45e 100644 --- a/src/backend/app/organization/organization_schemas.py +++ b/src/backend/app/organisations/organisation_schemas.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with FMTM. If not, see . # -"""Pydantic models for Organizations.""" +"""Pydantic models for Organisations.""" from re import sub from typing import Optional @@ -26,18 +26,18 @@ from app.models.enums import OrganisationType -# class OrganizationBase(BaseModel): +# class OrganisationBase(BaseModel): # """Base model for organisation to extend.""" class OrganisationIn(BaseModel): """Organisation to create from user input.""" - name: str = Field(Form(..., description="Organization name")) + name: str = Field(Form(..., description="Organisation name")) description: Optional[str] = Field( - Form(None, description="Organization description") + Form(None, description="Organisation description") ) - url: Optional[HttpUrl] = Field(Form(None, description="Organization website URL")) + url: Optional[HttpUrl] = Field(Form(None, description="Organisation website URL")) @field_validator("url", mode="after") @classmethod @@ -52,7 +52,7 @@ def convert_url_to_str(cls, value: HttpUrl) -> str: @computed_field @property def slug(self) -> str: - """Sanitise the organization name for use in a URL.""" + """Sanitise the organisation name for use in a URL.""" if self.name: # Remove special characters and replace spaces with hyphens slug = sub(r"[^\w\s-]", "", self.name).strip().lower().replace(" ", "-") @@ -65,7 +65,7 @@ class OrganisationEdit(OrganisationIn): """Organisation to edit via user input.""" # Override to make name optional - name: Optional[str] = Field(Form(None, description="Organization name")) + name: Optional[str] = Field(Form(None, description="Organisation name")) class OrganisationOut(BaseModel): diff --git a/src/backend/app/organization/organization_routes.py b/src/backend/app/organization/organization_routes.py deleted file mode 100644 index 60ec9954fa..0000000000 --- a/src/backend/app/organization/organization_routes.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2022, 2023 Humanitarian OpenStreetMap Team -# -# This file is part of FMTM. -# -# FMTM is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# FMTM is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with FMTM. If not, see . -# -"""Routes for organization management.""" - -from fastapi import ( - APIRouter, - Depends, - File, - UploadFile, -) -from sqlalchemy.orm import Session - -from app.db import database -from app.db.db_models import DbOrganisation -from app.organization import organization_crud, organization_schemas -from app.organization.organization_deps import org_exists - -router = APIRouter( - prefix="/organization", - tags=["organization"], - dependencies=[Depends(database.get_db)], - responses={404: {"description": "Not found"}}, -) - - -@router.get("/", response_model=list[organization_schemas.OrganisationOut]) -def get_organisations( - db: Session = Depends(database.get_db), -) -> list[organization_schemas.OrganisationOut]: - """Get a list of all organizations.""" - return organization_crud.get_organisations(db) - - -@router.get("/{org_id}", response_model=organization_schemas.OrganisationOut) -async def get_organization_detail( - organization: DbOrganisation = Depends(org_exists), - db: Session = Depends(database.get_db), -): - """Get a specific organization by id or name.""" - return organization - - -@router.post("/", response_model=organization_schemas.OrganisationOut) -async def create_organization( - org: organization_schemas.OrganisationIn = Depends(), - logo: UploadFile = File(None), - db: Session = Depends(database.get_db), -) -> organization_schemas.OrganisationOut: - """Create an organization with the given details.""" - return await organization_crud.create_organization(db, org, logo) - - -@router.patch("/{org_id}/", response_model=organization_schemas.OrganisationOut) -async def update_organization( - new_values: organization_schemas.OrganisationEdit = Depends(), - logo: UploadFile = File(None), - organization: DbOrganisation = Depends(org_exists), - db: Session = Depends(database.get_db), -): - """Partial update for an existing organization.""" - return await organization_crud.update_organization( - db, organization, new_values, logo - ) - - -@router.delete("/{org_id}") -async def delete_organisations( - organization: DbOrganisation = Depends(org_exists), - db: Session = Depends(database.get_db), -): - """Delete an organization.""" - return await organization_crud.delete_organization(db, organization) diff --git a/src/backend/app/projects/project_crud.py b/src/backend/app/projects/project_crud.py index 295fedf945..b2d2f74df3 100644 --- a/src/backend/app/projects/project_crud.py +++ b/src/backend/app/projects/project_crud.py @@ -64,7 +64,7 @@ from app.db import db_models from app.db.database import get_db from app.db.postgis_utils import geojson_to_flatgeobuf, geometry_to_geojson, timestamp -from app.organization import organization_crud +from app.organisations import organisation_crud from app.projects import project_schemas from app.s3 import add_obj_to_bucket, get_obj_from_bucket from app.tasks import tasks_crud @@ -2362,7 +2362,7 @@ async def get_pagination(page: int, count: int, results_per_page: int, total: in async def get_dashboard_detail(project_id: int, db: Session): """Get project details for project dashboard.""" project = await get_project(db, project_id) - db_organization = await organization_crud.get_organisation_by_id( + db_organisation = await organisation_crud.get_organisation_by_id( db, project.organisation_id ) @@ -2398,9 +2398,9 @@ async def get_dashboard_detail(project_id: int, db: Session): ) project.total_tasks = await tasks_crud.get_task_count_in_project(db, project_id) - project.organization, project.organization_logo = ( - db_organization.name, - db_organization.logo, + project.organisation, project.organisation_logo = ( + db_organisation.name, + db_organisation.logo, ) project.total_contributors = contributors diff --git a/src/backend/app/projects/project_routes.py b/src/backend/app/projects/project_routes.py index 10165570dd..18e5ce3e31 100644 --- a/src/backend/app/projects/project_routes.py +++ b/src/backend/app/projects/project_routes.py @@ -49,7 +49,7 @@ from app.projects import project_crud, project_deps, project_schemas from app.projects.project_crud import check_crs from app.static import data_path -from app.submission import submission_crud +from app.submissions import submission_crud from app.tasks import tasks_crud router = APIRouter( diff --git a/src/backend/app/projects/project_schemas.py b/src/backend/app/projects/project_schemas.py index 9ee400627e..db243f29a6 100644 --- a/src/backend/app/projects/project_schemas.py +++ b/src/backend/app/projects/project_schemas.py @@ -184,10 +184,10 @@ class ProjectDashboard(BaseModel): """Project details dashboard.""" project_name_prefix: str - organization: str + organisation: str total_tasks: int created: datetime - organization_logo: Optional[str] = None + organisation_logo: Optional[str] = None total_submission: Optional[int] = None total_contributors: Optional[int] = None last_active: Optional[Union[str, datetime]] = None diff --git a/src/backend/app/submission/__init__.py b/src/backend/app/submissions/__init__.py similarity index 100% rename from src/backend/app/submission/__init__.py rename to src/backend/app/submissions/__init__.py diff --git a/src/backend/app/submission/submission_crud.py b/src/backend/app/submissions/submission_crud.py similarity index 100% rename from src/backend/app/submission/submission_crud.py rename to src/backend/app/submissions/submission_crud.py diff --git a/src/backend/app/submission/submission_routes.py b/src/backend/app/submissions/submission_routes.py similarity index 99% rename from src/backend/app/submission/submission_routes.py rename to src/backend/app/submissions/submission_routes.py index 24771d5445..d5000ad184 100644 --- a/src/backend/app/submission/submission_routes.py +++ b/src/backend/app/submissions/submission_routes.py @@ -32,7 +32,7 @@ from app.config import settings from app.db import database from app.projects import project_crud, project_schemas -from app.submission import submission_crud +from app.submissions import submission_crud from app.tasks import tasks_crud router = APIRouter( diff --git a/src/backend/app/submission/submission_schemas.py b/src/backend/app/submissions/submission_schemas.py similarity index 100% rename from src/backend/app/submission/submission_schemas.py rename to src/backend/app/submissions/submission_schemas.py diff --git a/src/backend/app/users/user_crud.py b/src/backend/app/users/user_crud.py index 922d2508c9..95790f536e 100644 --- a/src/backend/app/users/user_crud.py +++ b/src/backend/app/users/user_crud.py @@ -62,7 +62,6 @@ async def create_user_roles(user_role: user_schemas.UserRoles, db: Session): db_user_role = db_models.DbUserRoles( user_id=user_role.user_id, role=user_role.role, - organization_id=user_role.organization_id, project_id=user_role.project_id, ) diff --git a/src/backend/app/users/user_routes.py b/src/backend/app/users/user_routes.py index 085c49e15d..9bfffd3fee 100644 --- a/src/backend/app/users/user_routes.py +++ b/src/backend/app/users/user_routes.py @@ -77,48 +77,6 @@ async def get_user_by_identifier(id: str, db: Session = Depends(database.get_db) return user -@router.post("/user-role") -async def create_user_role( - user_role: user_schemas.UserRoles, db: Session = Depends(database.get_db) -): - """Create a new user role. - - # FIXME is this endpoint really necessary? - - The role can be: - - Admin - - Organization Admin - - Field Admin - - Mapper - - Validator - - Read Only - - The request param `user_role` is a json of user_id, organization_id, - project_id, user_role: - user_id (required): ID of the user for whom the role is being created - organization_id (optional): ID of the organization for which the - user is being assigned a role - project_id (optional): ID of the project for which the user is - being assigned a role - user_role (required): Role being assigned to the user - - Response: - Status Code 200 (OK): If the role is successfully created - Status Code 400 (Bad Request): If the user is already assigned a role - """ - existing_user_role = await user_crud.get_user_role_by_user_id( - db, user_id=user_role.user_id - ) - if existing_user_role is not None: - raise HTTPException(status_code=400, detail="User is already assigned a role") - - user = await user_crud.get_user(db, user_id=user_role.user_id) - if user is None: - raise HTTPException(status_code=404, detail="User not found") - - return await user_crud.create_user_roles(user_role, db) - - @router.get("/user-role-options/") async def get_user_roles(): """Check for available user role options.""" diff --git a/src/backend/app/users/user_schemas.py b/src/backend/app/users/user_schemas.py index df16a42c04..f5a2822e9d 100644 --- a/src/backend/app/users/user_schemas.py +++ b/src/backend/app/users/user_schemas.py @@ -53,6 +53,5 @@ class UserRoles(BaseModel): """User details with role, org, and associated project.""" user_id: int - organization_id: Optional[int] = None project_id: Optional[int] = None role: UserRole diff --git a/src/backend/tests/conftest.py b/src/backend/tests/conftest.py index d68674ca98..68bdcf7ae4 100644 --- a/src/backend/tests/conftest.py +++ b/src/backend/tests/conftest.py @@ -94,7 +94,7 @@ def user(db): @pytest.fixture(scope="function") -def organization(db): +def organisation(db): """A test organisation.""" db_org = DbOrganisation( name="test_org_qwerty", @@ -109,7 +109,7 @@ def organization(db): @pytest.fixture(scope="function") -async def project(db, user, organization): +async def project(db, user, organisation): """A test project, using the test user and org.""" project_metadata = ProjectUpload( author=User(username=user.username, id=user.id), @@ -125,7 +125,7 @@ async def project(db, user, organization): odk_central_password=os.getenv("ODK_CENTRAL_PASSWD"), ), hashtags=["hot-fmtm"], - organisation_id=organization.id, + organisation_id=organisation.id, ) # Create ODK Central Project @@ -162,18 +162,18 @@ async def project(db, user, organization): # @pytest.fixture(scope="function") # def get_ids(db, project): # user_id_query = text(f"SELECT id FROM {DbUser.__table__.name} LIMIT 1") -# organization_id_query = text( +# organisation_id_query = text( # f"SELECT id FROM {DbOrganisation.__table__.name} LIMIT 1" # ) # project_id_query = text(f"SELECT id FROM {DbProject.__table__.name} LIMIT 1") # user_id = db.execute(user_id_query).scalar() -# organization_id = db.execute(organization_id_query).scalar() +# organisation_id = db.execute(organisation_id_query).scalar() # project_id = db.execute(project_id_query).scalar() # data = { # "user_id": user_id, -# "organization_id": organization_id, +# "organisation_id": organisation_id, # "project_id": project_id, # } # log.debug(f"get_ids return: {data}") diff --git a/src/backend/tests/test_projects_routes.py b/src/backend/tests/test_projects_routes.py index 58605fe329..57f067da4a 100644 --- a/src/backend/tests/test_projects_routes.py +++ b/src/backend/tests/test_projects_routes.py @@ -44,7 +44,7 @@ odk_central_password = os.getenv("ODK_CENTRAL_PASSWD") -async def test_create_project(client, organization, user): +async def test_create_project(client, organisation, user): """Test project creation endpoint.""" project_data = { "author": {"username": user.username, "id": user.id}, @@ -60,7 +60,7 @@ async def test_create_project(client, organization, user): "odk_central_password": odk_central_password, }, "hashtags": ["hot-fmtm"], - "organisation_id": organization.id, + "organisation_id": organisation.id, } response = client.post("/projects/create_project", json=project_data) diff --git a/src/frontend/src/api/CreateProjectService.ts b/src/frontend/src/api/CreateProjectService.ts index ff0581e30c..45fdcbaaee 100755 --- a/src/frontend/src/api/CreateProjectService.ts +++ b/src/frontend/src/api/CreateProjectService.ts @@ -212,7 +212,7 @@ const OrganisationService: Function = (url: string) => { const resp: OrganisationListModel = getOrganisationListResponse.data; dispatch(CreateProjectActions.GetOrganisationList(resp)); } catch (error) { - dispatch(CreateProjectActions.GetOrganizationListLoading(false)); + dispatch(CreateProjectActions.GetOrganisationListLoading(false)); } }; diff --git a/src/frontend/src/api/OrganisationService.ts b/src/frontend/src/api/OrganisationService.ts new file mode 100644 index 0000000000..d0b1f45ba9 --- /dev/null +++ b/src/frontend/src/api/OrganisationService.ts @@ -0,0 +1,100 @@ +import axios from 'axios'; +import { HomeProjectCardModel } from '../models/home/homeModel'; +import { GetOrganisationDataModel, OrganisationModal } from '../models/organisation/organisationModel'; +import { CommonActions } from '../store/slices/CommonSlice'; +import { OrganisationAction } from '../store/slices/organisationSlice'; + +function appendObjectToFormData(formData, object) { + for (const [key, value] of Object.entries(object)) { + // if (key === 'logo') { + // formData.append(key, value[0]) + // } + formData.append(key, value); + } +} + +export const OrganisationService: Function = (url: string, payload: OrganisationModal) => { + return async (dispatch) => { + dispatch(CommonActions.PostOrganisationLoading(true)); + + const postOrganisation = async (url, payload) => { + try { + const generateApiFormData = new FormData(); + appendObjectToFormData(generateApiFormData, payload); + await axios.post(url, generateApiFormData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + // const resp: HomeProjectCardModel = postOrganisationData.data; + // dispatch(CommonActions.SetOrganisationDetail(resp)) + dispatch(CommonActions.PostOrganisationLoading(false)); + } catch (error) { + dispatch(CommonActions.PostOrganisationLoading(false)); + } + }; + + await postOrganisation(url, payload); + }; +}; + +export const OrganisationDataService: Function = (url: string) => { + return async (dispatch) => { + dispatch(OrganisationAction.GetOrganisationDataLoading(true)); + const getOrganisationData = async (url) => { + try { + const getOrganisationDataResponse = await axios.get(url); + const response: GetOrganisationDataModel = getOrganisationDataResponse.data; + dispatch(OrganisationAction.GetOrganisationsData(response)); + } catch (error) { + dispatch(OrganisationAction.GetOrganisationDataLoading(false)); + } + }; + await getOrganisationData(url); + }; +}; + +export const PostOrganisationDataService: Function = (url: string, payload: any) => { + return async (dispatch) => { + dispatch(OrganisationAction.PostOrganisationDataLoading(true)); + + const postOrganisationData = async (url, payload) => { + dispatch(OrganisationAction.SetOrganisationFormData(payload)); + + try { + const generateApiFormData = new FormData(); + appendObjectToFormData(generateApiFormData, payload); + + const postOrganisationData = await axios.post(url, payload, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + + const resp: HomeProjectCardModel = postOrganisationData.data; + dispatch(OrganisationAction.PostOrganisationDataLoading(false)); + dispatch(OrganisationAction.postOrganisationData(resp)); + dispatch( + CommonActions.SetSnackBar({ + open: true, + message: 'Organization Successfully Created.', + variant: 'success', + duration: 2000, + }), + ); + } catch (error: any) { + dispatch( + CommonActions.SetSnackBar({ + open: true, + message: error.response.data.detail, + variant: 'error', + duration: 2000, + }), + ); + dispatch(OrganisationAction.PostOrganisationDataLoading(false)); + } + }; + + await postOrganisationData(url, payload); + }; +}; diff --git a/src/frontend/src/api/OrganizationService.ts b/src/frontend/src/api/OrganizationService.ts deleted file mode 100644 index 1aba3c4fe6..0000000000 --- a/src/frontend/src/api/OrganizationService.ts +++ /dev/null @@ -1,100 +0,0 @@ -import axios from 'axios'; -import { HomeProjectCardModel } from '../models/home/homeModel'; -import { GetOrganizationDataModel, OrganizationModal } from '../models/organization/organizationModel'; -import { CommonActions } from '../store/slices/CommonSlice'; -import { OrganizationAction } from '../store/slices/organizationSlice'; - -function appendObjectToFormData(formData, object) { - for (const [key, value] of Object.entries(object)) { - // if (key === 'logo') { - // formData.append(key, value[0]) - // } - formData.append(key, value); - } -} - -export const OrganizationService: Function = (url: string, payload: OrganizationModal) => { - return async (dispatch) => { - dispatch(CommonActions.PostOrganizationLoading(true)); - - const postOrganization = async (url, payload) => { - try { - const generateApiFormData = new FormData(); - appendObjectToFormData(generateApiFormData, payload); - await axios.post(url, generateApiFormData, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }); - // const resp: HomeProjectCardModel = postOrganizationData.data; - // dispatch(CommonActions.SetOrganizationDetail(resp)) - dispatch(CommonActions.PostOrganizationLoading(false)); - } catch (error) { - dispatch(CommonActions.PostOrganizationLoading(false)); - } - }; - - await postOrganization(url, payload); - }; -}; - -export const OrganizationDataService: Function = (url: string) => { - return async (dispatch) => { - dispatch(OrganizationAction.GetOrganizationDataLoading(true)); - const getOrganizationData = async (url) => { - try { - const getOrganizationDataResponse = await axios.get(url); - const response: GetOrganizationDataModel = getOrganizationDataResponse.data; - dispatch(OrganizationAction.GetOrganizationsData(response)); - } catch (error) { - dispatch(OrganizationAction.GetOrganizationDataLoading(false)); - } - }; - await getOrganizationData(url); - }; -}; - -export const PostOrganizationDataService: Function = (url: string, payload: any) => { - return async (dispatch) => { - dispatch(OrganizationAction.PostOrganizationDataLoading(true)); - - const postOrganizationData = async (url, payload) => { - dispatch(OrganizationAction.SetOrganizationFormData(payload)); - - try { - const generateApiFormData = new FormData(); - appendObjectToFormData(generateApiFormData, payload); - - const postOrganizationData = await axios.post(url, payload, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }); - - const resp: HomeProjectCardModel = postOrganizationData.data; - dispatch(OrganizationAction.PostOrganizationDataLoading(false)); - dispatch(OrganizationAction.postOrganizationData(resp)); - dispatch( - CommonActions.SetSnackBar({ - open: true, - message: 'Organization Successfully Created.', - variant: 'success', - duration: 2000, - }), - ); - } catch (error: any) { - dispatch( - CommonActions.SetSnackBar({ - open: true, - message: error.response.data.detail, - variant: 'error', - duration: 2000, - }), - ); - dispatch(OrganizationAction.PostOrganizationDataLoading(false)); - } - }; - - await postOrganizationData(url, payload); - }; -}; diff --git a/src/frontend/src/components/ProjectDetailsV2/ProjectInfo.tsx b/src/frontend/src/components/ProjectDetailsV2/ProjectInfo.tsx index d3e22756cd..2a42f6ab89 100644 --- a/src/frontend/src/components/ProjectDetailsV2/ProjectInfo.tsx +++ b/src/frontend/src/components/ProjectDetailsV2/ProjectInfo.tsx @@ -87,12 +87,12 @@ const ProjectInfo = () => {
Organization Photo
-

{projectDashboardDetail?.organization}

+

{projectDashboardDetail?.organisation}

)} diff --git a/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx b/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx index 3a5bb25f01..1952e93632 100644 --- a/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx +++ b/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx @@ -19,9 +19,9 @@ const ProjectDetailsForm = ({ flag }) => { const navigate = useNavigate(); const projectDetails: any = useAppSelector((state) => state.createproject.projectDetails); - const organizationListData: any = useAppSelector((state) => state.createproject.organizationList); + const organisationListData: any = useAppSelector((state) => state.createproject.organisationList); - const organizationList = organizationListData.map((item) => ({ label: item.name, value: item.id })); + const organisationList = organisationListData.map((item) => ({ label: item.name, value: item.id })); const submission = () => { dispatch(CreateProjectActions.SetIndividualProjectDetailsData(values)); @@ -36,7 +36,7 @@ const ProjectDetailsForm = ({ flag }) => { ); const onFocus = () => { - dispatch(OrganisationService(`${import.meta.env.VITE_API_URL}/organization/`)); + dispatch(OrganisationService(`${import.meta.env.VITE_API_URL}/organisation/`)); }; useEffect(() => { @@ -185,7 +185,7 @@ const ProjectDetailsForm = ({ flag }) => { { /> createPopup('Create Organization', 'createOrganization?popup=true')} + onClick={() => createPopup('Create Organization', 'createOrganisation?popup=true')} /> {errors.organisation_id && ( diff --git a/src/frontend/src/components/createproject/ProjectDetailsForm.tsx b/src/frontend/src/components/createproject/ProjectDetailsForm.tsx index 1003d4bb6c..fa66118c08 100755 --- a/src/frontend/src/components/createproject/ProjectDetailsForm.tsx +++ b/src/frontend/src/components/createproject/ProjectDetailsForm.tsx @@ -22,7 +22,7 @@ const ProjectDetailsForm: React.FC = () => { const projectDetails: any = useAppSelector((state) => state.createproject.projectDetails); //we use use selector from redux to get all state of projectDetails from createProject slice - const organizationListData: any = useAppSelector((state) => state.createproject.organizationList); + const organisationListData: any = useAppSelector((state) => state.createproject.organisationList); //we use use selector from redux to get all state of projectDetails from createProject slice const submission = () => { @@ -56,12 +56,12 @@ const ProjectDetailsForm: React.FC = () => { }, // or className: 'your-class' }; }; - // Changed OrganizationList Data into the Picker Component Format i.e label and value - const organizationList = organizationListData.map((item) => ({ label: item.name, value: item.id })); + // Changed OrganisationList Data into the Picker Component Format i.e label and value + const organisationList = organisationListData.map((item) => ({ label: item.name, value: item.id })); // User has switched back to the tab const onFocus = () => { - dispatch(OrganisationService(`${import.meta.env.VITE_API_URL}/organization/`)); + dispatch(OrganisationService(`${import.meta.env.VITE_API_URL}/organisation/`)); }; useEffect(() => { window.addEventListener('focus', onFocus); @@ -151,14 +151,14 @@ const ProjectDetailsForm: React.FC = () => { handleCustomChange('organisation_id', e.target.value); }} > - {organizationList?.map((org) => ( + {organisationList?.map((org) => ( {org.label} ))} createPopup('Create Organization', 'createOrganization?popup=true')} + onClick={() => createPopup('Create Organization', 'createOrganisation?popup=true')} sx={{ width: 'auto' }} // disabled={qrcode == "" ? true : false} color="info" diff --git a/src/frontend/src/components/editproject/EditProjectDetails.tsx b/src/frontend/src/components/editproject/EditProjectDetails.tsx index 2c85073550..a997c39b47 100644 --- a/src/frontend/src/components/editproject/EditProjectDetails.tsx +++ b/src/frontend/src/components/editproject/EditProjectDetails.tsx @@ -11,7 +11,7 @@ const EditProjectDetails = ({ projectId }) => { const editProjectDetails: any = CoreModules.useAppSelector((state) => state.createproject.editProjectDetails); // //we use use selector from redux to get all state of projectDetails from createProject slice - const organizationListData: any = CoreModules.useAppSelector((state) => state.createproject.organizationList); + const organisationListData: any = CoreModules.useAppSelector((state) => state.createproject.organisationList); // //we use use selector from redux to get all state of projectDetails from createProject slice const defaultTheme: any = CoreModules.useAppSelector((state) => state.theme.hotTheme); @@ -35,7 +35,7 @@ const EditProjectDetails = ({ projectId }) => { submission, EditProjectValidation, ); - const organizationList = organizationListData.map((item) => ({ label: item.name, value: item.id })); + const organisationList = organisationListData.map((item) => ({ label: item.name, value: item.id })); const inputFormStyles = () => { return { style: { @@ -93,18 +93,18 @@ const EditProjectDetails = ({ projectId }) => { }} labelId="demo-simple-select-label" id="demo-simple-select" - value={values.organization || ''} + value={values.organisation || ''} onChange={(e) => { - handleCustomChange('organization', e.target.value); }} + handleCustomChange('organisation', e.target.value); }} > - {organizationList?.map((org) => ( + {organisationList?.map((org) => ( {org.label} ))} - {errors.organization && ( + {errors.organisation && ( - {errors.organization} + {errors.organisation} )} */} diff --git a/src/frontend/src/components/editproject/validation/EditProjectDetailsValidation.ts b/src/frontend/src/components/editproject/validation/EditProjectDetailsValidation.ts index 06a0c6676a..b2f553953c 100644 --- a/src/frontend/src/components/editproject/validation/EditProjectDetailsValidation.ts +++ b/src/frontend/src/components/editproject/validation/EditProjectDetailsValidation.ts @@ -1,5 +1,5 @@ interface ProjectValues { - organization: string; + organisation: string; name: string; username: string; id: string; @@ -10,7 +10,7 @@ interface ProjectValues { // odk_central_password: string; } interface ValidationErrors { - organization?: string; + organisation?: string; name?: string; username?: string; id?: string; @@ -25,8 +25,8 @@ const regexForSymbol = /_/g; function EditProjectValidation(values: ProjectValues) { const errors: ValidationErrors = {}; - // if (!values?.organization) { - // errors.organization = 'Organization is Required.'; + // if (!values?.organisation) { + // errors.organisation = 'Organization is Required.'; // } // if (!values?.odk_central_url) { // errors.odk_central_url = 'ODK Central Url is Required.'; diff --git a/src/frontend/src/components/organization/OrganizationAddForm.tsx b/src/frontend/src/components/organisation/OrganisationAddForm.tsx similarity index 91% rename from src/frontend/src/components/organization/OrganizationAddForm.tsx rename to src/frontend/src/components/organisation/OrganisationAddForm.tsx index 701d2f5cbd..1835200b37 100644 --- a/src/frontend/src/components/organization/OrganizationAddForm.tsx +++ b/src/frontend/src/components/organisation/OrganisationAddForm.tsx @@ -1,28 +1,28 @@ import React from 'react'; import CoreModules from '../../shared/CoreModules.js'; -import useForm from '../../hooks/useForm'; -import OrganizationAddValidation from './Validation/OrganizationAddValidation'; +import useForm from '../../hooks/useForm.js'; +import OrganisationAddValidation from './Validation/OrganisationAddValidation.js'; import { MenuItem, Select } from '@mui/material'; -import { OrganizationService } from '../../api/OrganizationService'; -import environment from '../../environment'; +import { OrganisationService } from '../../api/OrganisationService'; +import environment from '../../environment.js'; const formData = {}; -const organizationTypeList = ['FREE', 'DISCOUNTED', 'FULL_FEE']; -const organizationDataList = organizationTypeList.map((item, index) => ({ label: item, value: index + 1 })); -const OrganizationAddForm = () => { +const organisationTypeList = ['FREE', 'DISCOUNTED', 'FULL_FEE']; +const organisationDataList = organisationTypeList.map((item, index) => ({ label: item, value: index + 1 })); +const OrganisationAddForm = () => { const dispatch = CoreModules.useAppDispatch(); const defaultTheme: any = CoreModules.useAppSelector((state) => state.theme.hotTheme); const submission = () => { // eslint-disable-next-line no-use-before-define // submitForm(); - dispatch(OrganizationService(`${import.meta.env.VITE_API_URL}/organization/`, values)); + dispatch(OrganisationService(`${import.meta.env.VITE_API_URL}/organisation/`, values)); // navigate("/select-form", { replace: true, state: { values: values } }); }; const { handleSubmit, handleCustomChange, values, errors }: any = useForm( formData, submission, - OrganizationAddValidation, + OrganisationAddValidation, ); const inputFormStyles = () => { return { @@ -165,10 +165,10 @@ const OrganizationAddForm = () => { label="Organization Type" onChange={(e) => { handleCustomChange('type', e.target.value); - // dispatch(CreateProjectActions.SetProjectDetails({ key: 'organization', value: e.target.value })) + // dispatch(CreateProjectActions.SetProjectDetails({ key: 'organisation', value: e.target.value })) }} > - {organizationDataList?.map((org) => {org.label})} + {organisationDataList?.map((org) => {org.label})} {errors.type && ( @@ -198,6 +198,6 @@ const OrganizationAddForm = () => { ); }; -OrganizationAddForm.propTypes = {}; +OrganisationAddForm.propTypes = {}; -export default OrganizationAddForm; +export default OrganisationAddForm; diff --git a/src/frontend/src/components/organization/Validation/OrganizationAddValidation.tsx b/src/frontend/src/components/organisation/Validation/OrganisationAddValidation.tsx similarity index 84% rename from src/frontend/src/components/organization/Validation/OrganizationAddValidation.tsx rename to src/frontend/src/components/organisation/Validation/OrganisationAddValidation.tsx index d8fe122dda..891daebbb8 100644 --- a/src/frontend/src/components/organization/Validation/OrganizationAddValidation.tsx +++ b/src/frontend/src/components/organisation/Validation/OrganisationAddValidation.tsx @@ -1,4 +1,4 @@ -interface OrganizationValues { +interface OrganisationValues { logo: string; name: string; description: string; @@ -22,7 +22,7 @@ function isValidUrl(url: string) { } } -function OrganizationAddValidation(values: OrganizationValues) { +function OrganisationAddValidation(values: OrganisationValues) { const errors: ValidationErrors = {}; // if (!values?.logo) { @@ -43,4 +43,4 @@ function OrganizationAddValidation(values: OrganizationValues) { return errors; } -export default OrganizationAddValidation; +export default OrganisationAddValidation; diff --git a/src/frontend/src/models/organization/organizationModel.ts b/src/frontend/src/models/organization/organisationModel.ts similarity index 83% rename from src/frontend/src/models/organization/organizationModel.ts rename to src/frontend/src/models/organization/organisationModel.ts index a7795a55b1..02278511d3 100644 --- a/src/frontend/src/models/organization/organizationModel.ts +++ b/src/frontend/src/models/organization/organisationModel.ts @@ -1,4 +1,4 @@ -export interface OrganizationModal { +export interface OrganisationModal { name: string; description: string; url: string; @@ -20,7 +20,7 @@ export interface OrganisationListModel { url: string; } -export interface GetOrganizationDataModel { +export interface GetOrganisationDataModel { name: string; slug: string; description: string; @@ -30,7 +30,7 @@ export interface GetOrganizationDataModel { logo: string; url: string; } -export interface PostOrganizationDataModel { +export interface PostOrganisationDataModel { name: string; slug: string; description: string; diff --git a/src/frontend/src/routes.jsx b/src/frontend/src/routes.jsx index c25a443cce..5818226dee 100755 --- a/src/frontend/src/routes.jsx +++ b/src/frontend/src/routes.jsx @@ -10,8 +10,8 @@ import CreateProject from './views/CreateProject'; import EditProject from './views/EditProject'; import ProtectedRoute from './utilities/ProtectedRoute'; import NotFoundPage from './views/NotFound404'; -import Organization from './views/Organization'; -import CreateOrganization from './views/CreateOrganization'; +import Organisation from './views/Organisation'; +import CreateOrganisation from './views/CreateOrganisation'; import Authorized from './views/Authorized'; import SubmissionDetails from './views/SubmissionDetails'; import CreateNewProject from './views/CreateNewProject'; @@ -39,18 +39,18 @@ const routes = createBrowserRouter([ ), }, { - path: '/organization', + path: '/organisation', element: ( - + ), }, { - path: '/createOrganization', + path: '/createOrganisation', element: ( - + ), }, diff --git a/src/frontend/src/store/Store.ts b/src/frontend/src/store/Store.ts index cc20f452e9..05058a3470 100755 --- a/src/frontend/src/store/Store.ts +++ b/src/frontend/src/store/Store.ts @@ -6,7 +6,7 @@ import ProjectSlice from './slices/ProjectSlice'; import CreateProjectReducer from './slices/CreateProjectSlice'; import CommonSlice from './slices/CommonSlice'; import LoginSlice from './slices/LoginSlice'; -import OrganizationSlice from './slices/organizationSlice'; +import OrganisationSlice from './slices/organisationSlice'; import SubmissionSlice from './slices/SubmissionSlice'; import TaskSlice from './slices/TaskSlice'; import { persistReducer } from 'redux-persist'; @@ -31,7 +31,7 @@ const rootReducer = combineReducers({ theme: ThemeSlice.reducer, createproject: CreateProjectReducer, // createproject: persist('createproject', ['projectDetails', 'projectInfo'], CreateProjectReducer), - organization: OrganizationSlice.reducer, + organisation: OrganisationSlice.reducer, // added common slice in order to handle all the common things like snackbar etc common: CommonSlice.reducer, submission: SubmissionSlice.reducer, diff --git a/src/frontend/src/store/slices/CommonSlice.ts b/src/frontend/src/store/slices/CommonSlice.ts index c239074a54..9b5db5b957 100755 --- a/src/frontend/src/store/slices/CommonSlice.ts +++ b/src/frontend/src/store/slices/CommonSlice.ts @@ -9,7 +9,7 @@ const CommonSlice = CoreModules.createSlice({ duration: 0, }, loading: false, - postOrganizationLoading: false, + postOrganisationLoading: false, currentStepFormStep: { create_project: { step: 1, @@ -23,8 +23,8 @@ const CommonSlice = CoreModules.createSlice({ SetLoading(state, action) { state.loading = action.payload; }, - PostOrganizationLoading(state, action) { - state.organization = action.payload; + PostOrganisationLoading(state, action) { + state.organisation = action.payload; }, SetCurrentStepFormStep(state, action) { state.currentStepFormStep[action.payload.flag] = { step: action.payload.step }; diff --git a/src/frontend/src/store/slices/CreateProjectSlice.ts b/src/frontend/src/store/slices/CreateProjectSlice.ts index f037379fc9..b8e677609d 100755 --- a/src/frontend/src/store/slices/CreateProjectSlice.ts +++ b/src/frontend/src/store/slices/CreateProjectSlice.ts @@ -24,8 +24,8 @@ export const initialState: CreateProjectStateTypes = { formCategoryList: [], formCategoryLoading: false, generateQrLoading: false, - organizationList: [], - organizationListLoading: false, + organisationList: [], + organisationListLoading: false, generateQrSuccess: null, generateProjectLogLoading: false, generateProjectLog: null, @@ -113,10 +113,10 @@ const CreateProject = createSlice({ state.generateQrLoading = action.payload; }, GetOrganisationList(state, action) { - state.organizationList = action.payload; + state.organisationList = action.payload; }, GetOrganisationListLoading(state, action) { - state.organizationListLoading = action.payload; + state.organisationListLoading = action.payload; }, GenerateProjectQRSuccess(state, action) { if (action.payload.status === 'SUCCESS') { diff --git a/src/frontend/src/store/slices/organisationSlice.ts b/src/frontend/src/store/slices/organisationSlice.ts new file mode 100644 index 0000000000..26069f4821 --- /dev/null +++ b/src/frontend/src/store/slices/organisationSlice.ts @@ -0,0 +1,32 @@ +import CoreModules from '../../shared/CoreModules.js'; + +const OrganisationSlice = CoreModules.createSlice({ + name: 'organisation', + initialState: { + organisationFormData: {}, + organisationData: [], + postOrganisationData: null, + organisationDataLoading: false, + postOrganisationDataLoading: false, + }, + reducers: { + GetOrganisationsData(state, action) { + state.oraganizationData = action.payload; + }, + GetOrganisationDataLoading(state, action) { + state.organisationDataLoading = action.payload; + }, + postOrganisationData(state, action) { + state.postOrganisationData = action.payload; + }, + PostOrganisationDataLoading(state, action) { + state.postOrganisationDataLoading = action.payload; + }, + SetOrganisationFormData(state, action) { + state.organisationFormData = action.payload; + }, + }, +}); + +export const OrganisationAction = OrganisationSlice.actions; +export default OrganisationSlice; diff --git a/src/frontend/src/store/slices/organizationSlice.ts b/src/frontend/src/store/slices/organizationSlice.ts deleted file mode 100644 index f4d85c9937..0000000000 --- a/src/frontend/src/store/slices/organizationSlice.ts +++ /dev/null @@ -1,32 +0,0 @@ -import CoreModules from '../../shared/CoreModules.js'; - -const OrganizationSlice = CoreModules.createSlice({ - name: 'organization', - initialState: { - organizationFormData: {}, - organizationData: [], - postOrganizationData: null, - organizationDataLoading: false, - postOrganizationDataLoading: false, - }, - reducers: { - GetOrganizationsData(state, action) { - state.oraganizationData = action.payload; - }, - GetOrganizationDataLoading(state, action) { - state.organizationDataLoading = action.payload; - }, - postOrganizationData(state, action) { - state.postOrganizationData = action.payload; - }, - PostOrganizationDataLoading(state, action) { - state.postOrganizationDataLoading = action.payload; - }, - SetOrganizationFormData(state, action) { - state.organizationFormData = action.payload; - }, - }, -}); - -export const OrganizationAction = OrganizationSlice.actions; -export default OrganizationSlice; diff --git a/src/frontend/src/store/types/ICreateProject.ts b/src/frontend/src/store/types/ICreateProject.ts index bd7fd27e08..2ce4a158a6 100644 --- a/src/frontend/src/store/types/ICreateProject.ts +++ b/src/frontend/src/store/types/ICreateProject.ts @@ -10,8 +10,8 @@ export type CreateProjectStateTypes = { formCategoryList: FormCategoryListTypes | []; formCategoryLoading: boolean; generateQrLoading: boolean; - organizationList: OrganizationListTypes[]; - organizationListLoading: boolean; + organisationList: OrganisationListTypes[]; + organisationListLoading: boolean; generateQrSuccess: GenerateQrSuccessTypes | null; generateProjectLogLoading: boolean; generateProjectLog: GenerateProjectLogTypes | null; @@ -102,7 +102,7 @@ export type ProjectDetailsTypes = { no_of_buildings: number; odk_central_user?: string; odk_central_password?: string; - organization?: number; + organisation?: number; odk_central_url?: string; name?: string; hashtags?: string; @@ -130,7 +130,7 @@ export type GenerateQrSuccessTypes = { task_id: string; }; -export type OrganizationListTypes = { +export type OrganisationListTypes = { logo: string; id: number; url: string; diff --git a/src/frontend/src/utilities/CustomDrawer.jsx b/src/frontend/src/utilities/CustomDrawer.jsx index 268e42a080..688ccf2a20 100644 --- a/src/frontend/src/utilities/CustomDrawer.jsx +++ b/src/frontend/src/utilities/CustomDrawer.jsx @@ -50,7 +50,7 @@ export default function CustomDrawer({ open, placement, size, type, onClose, onS }, { name: 'Manage Organizations', - ref: '/organization', + ref: '/organisation', isExternalLink: false, isActive: true, }, diff --git a/src/frontend/src/utilities/PrimaryAppBar.tsx b/src/frontend/src/utilities/PrimaryAppBar.tsx index 6bee67c1a9..9786e43eb6 100755 --- a/src/frontend/src/utilities/PrimaryAppBar.tsx +++ b/src/frontend/src/utilities/PrimaryAppBar.tsx @@ -115,7 +115,7 @@ export default function PrimaryAppBar() { onClick={() => setActiveTab(0)} /> - + { +const CreateOrganisationForm = () => { const dispatch = CoreModules.useAppDispatch(); const navigate = useNavigate(); const [searchParams, setSearchParams] = useSearchParams(); const defaultTheme: any = CoreModules.useAppSelector((state) => state.theme.hotTheme); - const postOrganizationData: any = CoreModules.useAppSelector((state) => state.organization.postOrganizationData); + const postOrganisationData: any = CoreModules.useAppSelector((state) => state.organisation.postOrganisationData); - const organizationFormData: any = CoreModules.useAppSelector((state) => state.organization.organizationFormData); + const organisationFormData: any = CoreModules.useAppSelector((state) => state.organisation.organisationFormData); const submission = () => { - dispatch(PostOrganizationDataService(`${import.meta.env.VITE_API_URL}/organization/`, values)); + dispatch(PostOrganisationDataService(`${import.meta.env.VITE_API_URL}/organisation/`, values)); }; const { handleSubmit, handleCustomChange, values, errors }: any = useForm( - organizationFormData, + organisationFormData, submission, - OrganizationAddValidation, + OrganisationAddValidation, ); const inputFormStyles = () => { return { @@ -35,16 +35,16 @@ const CreateOrganizationForm = () => { }; useEffect(() => { - if (postOrganizationData) { - dispatch(OrganizationAction.postOrganizationData(null)); - dispatch(OrganizationAction.SetOrganizationFormData({})); + if (postOrganisationData) { + dispatch(OrganisationAction.postOrganisationData(null)); + dispatch(OrganisationAction.SetOrganisationFormData({})); if (searchParams.get('popup') === 'true') { window.close(); } else { - navigate('/organization'); + navigate('/organisation'); } } - }, [postOrganizationData]); + }, [postOrganisationData]); return ( { ); }; -export default CreateOrganizationForm; +export default CreateOrganisationForm; diff --git a/src/frontend/src/views/EditProject.tsx b/src/frontend/src/views/EditProject.tsx index 8f49a394a8..6ec093313a 100755 --- a/src/frontend/src/views/EditProject.tsx +++ b/src/frontend/src/views/EditProject.tsx @@ -26,7 +26,7 @@ const EditProject: React.FC = () => { }, }; useEffect(() => { - dispatch(OrganisationService(`${import.meta.env.VITE_API_URL}/organization/`)); + dispatch(OrganisationService(`${import.meta.env.VITE_API_URL}/organisation/`)); if (decodedProjectId) { dispatch(GetIndividualProjectDetails(`${import.meta.env.VITE_API_URL}/projects/${decodedProjectId}`)); diff --git a/src/frontend/src/views/Organization.tsx b/src/frontend/src/views/Organisation.tsx similarity index 94% rename from src/frontend/src/views/Organization.tsx rename to src/frontend/src/views/Organisation.tsx index 24aa6ed8fe..758daaec97 100644 --- a/src/frontend/src/views/Organization.tsx +++ b/src/frontend/src/views/Organisation.tsx @@ -2,9 +2,9 @@ import React, { useEffect, useState } from 'react'; import CoreModules from '../shared/CoreModules'; import AssetModules from '../shared/AssetModules'; import environment from '../environment'; -import { OrganizationDataService } from '../api/OrganizationService'; +import { OrganisationDataService } from '../api/OrganisationService'; -const Organization = () => { +const Organisation = () => { const cardStyle = { padding: 2, display: 'flex', @@ -25,14 +25,14 @@ const Organization = () => { const dispatch = CoreModules.useAppDispatch(); - const oraganizationData: any = CoreModules.useAppSelector((state) => state.organization.oraganizationData); + const oraganizationData: any = CoreModules.useAppSelector((state) => state.organisation.oraganizationData); console.log(oraganizationData, 'oraganizationData'); const filteredCardData = oraganizationData?.filter((data) => data.name.toLowerCase().includes(searchKeyword.toLowerCase()), ); useEffect(() => { - dispatch(OrganizationDataService(`${import.meta.env.VITE_API_URL}/organization/`)); + dispatch(OrganisationDataService(`${import.meta.env.VITE_API_URL}/organisation/`)); }, []); return ( @@ -48,7 +48,7 @@ const Organization = () => { >

MANAGE ORGANIZATIONS

- + { ); }; -export default Organization; +export default Organisation;