From 123b2076e81bd813002a79d36e6b468dc51ec6ce Mon Sep 17 00:00:00 2001 From: maanasb01 <maanasb01@gmail.com> Date: Mon, 20 Jan 2025 18:38:16 +0530 Subject: [PATCH] create crowdsource context & add login in plugin --- browser-extension/plugin/.env.development | 2 +- browser-extension/plugin/src/api.js | 21 +++ .../plugin/src/ui-components/pages/App.jsx | 1 + .../plugin/src/ui-components/pages/Debug.jsx | 129 +++++++++++++++--- .../src/ui-components/pages/SlurCreate.jsx | 2 +- .../lib/uli_community/user_contribution.ex | 104 ++++++++++++++ .../user_contribution/crowdsourced_slur.ex | 23 ++++ .../user_session_controller_api.ex | 2 +- ...250120074709_create_crowdsourced_slurs.exs | 19 +++ .../fixtures/user_contribution_fixtures.ex | 26 ++++ .../uli_community/user_contribution_test.exs | 71 ++++++++++ 11 files changed, 375 insertions(+), 25 deletions(-) create mode 100644 browser-extension/plugin/src/api.js create mode 100644 uli-community/lib/uli_community/user_contribution.ex create mode 100644 uli-community/lib/uli_community/user_contribution/crowdsourced_slur.ex create mode 100644 uli-community/priv/repo/migrations/20250120074709_create_crowdsourced_slurs.exs create mode 100644 uli-community/test/support/fixtures/user_contribution_fixtures.ex create mode 100644 uli-community/test/uli_community/user_contribution_test.exs diff --git a/browser-extension/plugin/.env.development b/browser-extension/plugin/.env.development index a41444a5..845728b3 100644 --- a/browser-extension/plugin/.env.development +++ b/browser-extension/plugin/.env.development @@ -1,4 +1,4 @@ ENVIRONMENT=development LOCAL_STORAGE_NAME=ogbvData -API_URL=http://localhost:3000 +API_URL=http://localhost:4000 MEDIA_URL=https://uli-media.tattle.co.in \ No newline at end of file diff --git a/browser-extension/plugin/src/api.js b/browser-extension/plugin/src/api.js new file mode 100644 index 00000000..b4c43452 --- /dev/null +++ b/browser-extension/plugin/src/api.js @@ -0,0 +1,21 @@ +import axios from "axios"; +import config from "./config"; + +const { API_URL } = config; + +export async function userLogin({email, password}){ + + console.log("INSIDE USERLOGIN: ") + try { + const response = await axios.post(`${API_URL}/api/auth/login`, { + email, + password + }); + console.log("RESPONSE IS: ",response) + console.log('Login successful:', response.data); + return response.data; + } catch (error) { + + throw error; + } +} diff --git a/browser-extension/plugin/src/ui-components/pages/App.jsx b/browser-extension/plugin/src/ui-components/pages/App.jsx index 410c3521..1ee00b7d 100644 --- a/browser-extension/plugin/src/ui-components/pages/App.jsx +++ b/browser-extension/plugin/src/ui-components/pages/App.jsx @@ -46,6 +46,7 @@ export function App() { async function navigatePreferences() { try { const userData = await getUserData(); + console.log("USER DATA: ", userData) const preferenceData = await getPreferenceData(); if (!ignore) { diff --git a/browser-extension/plugin/src/ui-components/pages/Debug.jsx b/browser-extension/plugin/src/ui-components/pages/Debug.jsx index 77ade592..d00902f2 100644 --- a/browser-extension/plugin/src/ui-components/pages/Debug.jsx +++ b/browser-extension/plugin/src/ui-components/pages/Debug.jsx @@ -9,7 +9,7 @@ import { TextInput, Heading } from 'grommet'; -import { UserContext } from '../atoms/AppContext'; +import { UserContext, NotificationContext } from '../atoms/AppContext'; import repository from '../../repository'; import config from '../../config'; import { useTranslation } from 'react-i18next'; @@ -18,41 +18,126 @@ const { getUserData, getPreferenceData, setUserData, setPreferenceData } = repository; const { resetAccount } = Api; import { Hide, View } from 'grommet-icons'; +import { userLogin } from '../../api'; export function Debug() { const { user, setUser } = useContext(UserContext); + const { showNotification } = useContext(NotificationContext); const [localStorageData, setLocalStorageData] = useState(undefined); const { t, i18n } = useTranslation(); + const [isResetChecked, setIsResetChecked] = useState(false); - useEffect(() => { - async function localStorage() { - const userData = await getUserData(); - const preferenceData = await getPreferenceData(); - if (!ignore) { - setLocalStorageData({ - user: userData, - preference: preferenceData - }); - } - } - let ignore = false; - localStorage(); - return () => { - ignore = true; - }; - }, []); - - return <Box>{user ? <Box>Logged in. Settings</Box> : <LoginForm />}</Box>; + // useEffect(() => { + // async function localStorage() { + // const userData = await getUserData(); + // const preferenceData = await getPreferenceData(); + // if (!ignore) { + // setLocalStorageData({ + // user: userData, + // preference: preferenceData + // }); + // } + // } + // let ignore = false; + // localStorage(); + // return () => { + // ignore = true; + // }; + // }, []); + + return ( + <Box> + {user ? ( + <Box> + <Text> + Hello, <b>{user?.email}</b> ! + </Text> + <Box + pad={'small'} + border={{ color: 'status-critical' }} + margin={{ top: 'xsmall' }} + fill={'horizontal'} + align="start" + > + <Text color={'status-critical'}> + Logout + </Text> + <Box height={'0.8em'}></Box> + <Box gap={'small'}> + <CheckBox + checked={isResetChecked} + label={"I am sure I want to logout from this account"} + onChange={(e) => + setIsResetChecked(e.target.checked) + } + /> + <Button + label={"Logout"} + disabled={!isResetChecked} + secondary + onClick={async()=>{ + await setUserData(undefined); + setUser(null); + }} + /> + </Box> + </Box> + </Box> + ) : ( + <LoginForm /> + )} + </Box> + ); } const LoginForm = () => { const [reveal, setReveal] = useState(false); const [formValues, setFormValues] = useState({ email: '', password: '' }); + const { showNotification } = useContext(NotificationContext); + const { user, setUser } = useContext(UserContext); - const handleSubmit = ({ value }) => { + async function handleSubmit({ value }) { console.log('Form Submitted:', value); - }; + + try { + let data = await userLogin(value); + + console.log('LOGIN SUCCESS: ', data); + showNotification({ + type: 'info', + message: 'Login Successful' + }); + + const { email, token } = data; + + let setData = { email, token }; + + await setUserData(setData); + setUser(setData); + } catch (error) { + console.error(error); + if (error?.response?.status === 401) { + // console.log('UNAUTHORIZED', error); + showNotification({ + type: 'error', + message: 'Unauthorized' + }); + } else if (error?.response?.status >= 500) { + // console.log('UNAUTHORIZED', error); + showNotification({ + type: 'error', + message: 'Server Error' + }); + } else { + // console.log('SOMETHING WENT WRONG', error); + showNotification({ + type: 'error', + message: 'Something Went Wrong' + }); + } + } + } return ( <Box> diff --git a/browser-extension/plugin/src/ui-components/pages/SlurCreate.jsx b/browser-extension/plugin/src/ui-components/pages/SlurCreate.jsx index fb402d7e..68621214 100644 --- a/browser-extension/plugin/src/ui-components/pages/SlurCreate.jsx +++ b/browser-extension/plugin/src/ui-components/pages/SlurCreate.jsx @@ -36,7 +36,7 @@ export function SlurCreate() { let newValue = slurCreatePluginToApi(value); // console.log(newValue); try { - await createSlurAndCategory(user.accessToken, newValue); + await createSlurAndCategory("dea07e31-417c-4547-9208-57ff7fcf2da8", newValue); navigate('/slur'); showNotification({ type: 'message', diff --git a/uli-community/lib/uli_community/user_contribution.ex b/uli-community/lib/uli_community/user_contribution.ex new file mode 100644 index 00000000..1a28bb84 --- /dev/null +++ b/uli-community/lib/uli_community/user_contribution.ex @@ -0,0 +1,104 @@ +defmodule UliCommunity.UserContribution do + @moduledoc """ + The UserContribution context. + """ + + import Ecto.Query, warn: false + alias UliCommunity.Repo + + alias UliCommunity.UserContribution.CrowdsourcedSlur + + @doc """ + Returns the list of crowdsourced_slurs. + + ## Examples + + iex> list_crowdsourced_slurs() + [%CrowdsourcedSlur{}, ...] + + """ + def list_crowdsourced_slurs do + Repo.all(CrowdsourcedSlur) + end + + @doc """ + Gets a single crowdsourced_slur. + + Raises `Ecto.NoResultsError` if the Crowdsourced slur does not exist. + + ## Examples + + iex> get_crowdsourced_slur!(123) + %CrowdsourcedSlur{} + + iex> get_crowdsourced_slur!(456) + ** (Ecto.NoResultsError) + + """ + def get_crowdsourced_slur!(id), do: Repo.get!(CrowdsourcedSlur, id) + + @doc """ + Creates a crowdsourced_slur. + + ## Examples + + iex> create_crowdsourced_slur(%{field: value}) + {:ok, %CrowdsourcedSlur{}} + + iex> create_crowdsourced_slur(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_crowdsourced_slur(attrs \\ %{}) do + %CrowdsourcedSlur{} + |> CrowdsourcedSlur.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a crowdsourced_slur. + + ## Examples + + iex> update_crowdsourced_slur(crowdsourced_slur, %{field: new_value}) + {:ok, %CrowdsourcedSlur{}} + + iex> update_crowdsourced_slur(crowdsourced_slur, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_crowdsourced_slur(%CrowdsourcedSlur{} = crowdsourced_slur, attrs) do + crowdsourced_slur + |> CrowdsourcedSlur.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a crowdsourced_slur. + + ## Examples + + iex> delete_crowdsourced_slur(crowdsourced_slur) + {:ok, %CrowdsourcedSlur{}} + + iex> delete_crowdsourced_slur(crowdsourced_slur) + {:error, %Ecto.Changeset{}} + + """ + def delete_crowdsourced_slur(%CrowdsourcedSlur{} = crowdsourced_slur) do + Repo.delete(crowdsourced_slur) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking crowdsourced_slur changes. + + ## Examples + + iex> change_crowdsourced_slur(crowdsourced_slur) + %Ecto.Changeset{data: %CrowdsourcedSlur{}} + + """ + def change_crowdsourced_slur(%CrowdsourcedSlur{} = crowdsourced_slur, attrs \\ %{}) do + CrowdsourcedSlur.changeset(crowdsourced_slur, attrs) + end +end diff --git a/uli-community/lib/uli_community/user_contribution/crowdsourced_slur.ex b/uli-community/lib/uli_community/user_contribution/crowdsourced_slur.ex new file mode 100644 index 00000000..2c7ee87b --- /dev/null +++ b/uli-community/lib/uli_community/user_contribution/crowdsourced_slur.ex @@ -0,0 +1,23 @@ +defmodule UliCommunity.UserContribution.CrowdsourcedSlur do + use Ecto.Schema + import Ecto.Changeset + + schema "crowdsourced_slurs" do + field :label, :string + field :category, {:array, :string} + field :level_of_severity, Ecto.Enum, values: [:low, :medium, :high] + field :casual, :boolean, default: false + field :appropriated, :boolean, default: false + field :appropriation_context, :boolean, default: false + field :meaning, :string + + timestamps(type: :utc_datetime) + end + + @doc false + def changeset(crowdsourced_slur, attrs) do + crowdsourced_slur + |> cast(attrs, [:label, :level_of_severity, :casual, :appropriated, :appropriation_context, :meaning, :category]) + |> validate_required([:label, :level_of_severity, :casual, :appropriated, :appropriation_context, :meaning, :category]) + end +end diff --git a/uli-community/lib/uli_community_web/controllers/user_session_controller_api.ex b/uli-community/lib/uli_community_web/controllers/user_session_controller_api.ex index 937428b0..eb495131 100644 --- a/uli-community/lib/uli_community_web/controllers/user_session_controller_api.ex +++ b/uli-community/lib/uli_community_web/controllers/user_session_controller_api.ex @@ -18,7 +18,7 @@ defmodule UliCommunityWeb.SessionControllerApi do user -> IO.inspect(user, label: "USER IS: ") with {:ok, token} <- Token.sign(%{user_id: user.id}) do - json(conn, %{token: token, message: "Token Generation Successful!"}) + json(conn, %{token: token, message: "Token Generation Successful!", email: user.email}) else _ -> conn diff --git a/uli-community/priv/repo/migrations/20250120074709_create_crowdsourced_slurs.exs b/uli-community/priv/repo/migrations/20250120074709_create_crowdsourced_slurs.exs new file mode 100644 index 00000000..509fdae5 --- /dev/null +++ b/uli-community/priv/repo/migrations/20250120074709_create_crowdsourced_slurs.exs @@ -0,0 +1,19 @@ +defmodule UliCommunity.Repo.Migrations.CreateCrowdsourcedSlurs do + use Ecto.Migration + + def change do + + execute("CREATE TYPE level_of_severity AS ENUM ('low', 'medium', 'high')") + create table(:crowdsourced_slurs) do + add :label, :string + add :level_of_severity, :level_of_severity + add :casual, :boolean, default: false, null: false + add :appropriated, :boolean, default: false, null: false + add :appropriation_context, :boolean, default: false, null: false + add :meaning, :text + add :category, {:array, :string} + + timestamps(type: :utc_datetime) + end + end +end diff --git a/uli-community/test/support/fixtures/user_contribution_fixtures.ex b/uli-community/test/support/fixtures/user_contribution_fixtures.ex new file mode 100644 index 00000000..70cb6933 --- /dev/null +++ b/uli-community/test/support/fixtures/user_contribution_fixtures.ex @@ -0,0 +1,26 @@ +defmodule UliCommunity.UserContributionFixtures do + @moduledoc """ + This module defines test helpers for creating + entities via the `UliCommunity.UserContribution` context. + """ + + @doc """ + Generate a crowdsourced_slur. + """ + def crowdsourced_slur_fixture(attrs \\ %{}) do + {:ok, crowdsourced_slur} = + attrs + |> Enum.into(%{ + appropriated: true, + appropriation_context: true, + casual: true, + category: ["option1", "option2"], + label: "some label", + level_of_severity: "some level_of_severity", + meaning: "some meaning" + }) + |> UliCommunity.UserContribution.create_crowdsourced_slur() + + crowdsourced_slur + end +end diff --git a/uli-community/test/uli_community/user_contribution_test.exs b/uli-community/test/uli_community/user_contribution_test.exs new file mode 100644 index 00000000..83bbcdd4 --- /dev/null +++ b/uli-community/test/uli_community/user_contribution_test.exs @@ -0,0 +1,71 @@ +defmodule UliCommunity.UserContributionTest do + use UliCommunity.DataCase + + alias UliCommunity.UserContribution + + describe "crowdsourced_slurs" do + alias UliCommunity.UserContribution.CrowdsourcedSlur + + import UliCommunity.UserContributionFixtures + + @invalid_attrs %{label: nil, category: nil, level_of_severity: nil, casual: nil, appropriated: nil, appropriation_context: nil, meaning: nil} + + test "list_crowdsourced_slurs/0 returns all crowdsourced_slurs" do + crowdsourced_slur = crowdsourced_slur_fixture() + assert UserContribution.list_crowdsourced_slurs() == [crowdsourced_slur] + end + + test "get_crowdsourced_slur!/1 returns the crowdsourced_slur with given id" do + crowdsourced_slur = crowdsourced_slur_fixture() + assert UserContribution.get_crowdsourced_slur!(crowdsourced_slur.id) == crowdsourced_slur + end + + test "create_crowdsourced_slur/1 with valid data creates a crowdsourced_slur" do + valid_attrs = %{label: "some label", category: ["option1", "option2"], level_of_severity: "some level_of_severity", casual: true, appropriated: true, appropriation_context: true, meaning: "some meaning"} + + assert {:ok, %CrowdsourcedSlur{} = crowdsourced_slur} = UserContribution.create_crowdsourced_slur(valid_attrs) + assert crowdsourced_slur.label == "some label" + assert crowdsourced_slur.category == ["option1", "option2"] + assert crowdsourced_slur.level_of_severity == "some level_of_severity" + assert crowdsourced_slur.casual == true + assert crowdsourced_slur.appropriated == true + assert crowdsourced_slur.appropriation_context == true + assert crowdsourced_slur.meaning == "some meaning" + end + + test "create_crowdsourced_slur/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = UserContribution.create_crowdsourced_slur(@invalid_attrs) + end + + test "update_crowdsourced_slur/2 with valid data updates the crowdsourced_slur" do + crowdsourced_slur = crowdsourced_slur_fixture() + update_attrs = %{label: "some updated label", category: ["option1"], level_of_severity: "some updated level_of_severity", casual: false, appropriated: false, appropriation_context: false, meaning: "some updated meaning"} + + assert {:ok, %CrowdsourcedSlur{} = crowdsourced_slur} = UserContribution.update_crowdsourced_slur(crowdsourced_slur, update_attrs) + assert crowdsourced_slur.label == "some updated label" + assert crowdsourced_slur.category == ["option1"] + assert crowdsourced_slur.level_of_severity == "some updated level_of_severity" + assert crowdsourced_slur.casual == false + assert crowdsourced_slur.appropriated == false + assert crowdsourced_slur.appropriation_context == false + assert crowdsourced_slur.meaning == "some updated meaning" + end + + test "update_crowdsourced_slur/2 with invalid data returns error changeset" do + crowdsourced_slur = crowdsourced_slur_fixture() + assert {:error, %Ecto.Changeset{}} = UserContribution.update_crowdsourced_slur(crowdsourced_slur, @invalid_attrs) + assert crowdsourced_slur == UserContribution.get_crowdsourced_slur!(crowdsourced_slur.id) + end + + test "delete_crowdsourced_slur/1 deletes the crowdsourced_slur" do + crowdsourced_slur = crowdsourced_slur_fixture() + assert {:ok, %CrowdsourcedSlur{}} = UserContribution.delete_crowdsourced_slur(crowdsourced_slur) + assert_raise Ecto.NoResultsError, fn -> UserContribution.get_crowdsourced_slur!(crowdsourced_slur.id) end + end + + test "change_crowdsourced_slur/1 returns a crowdsourced_slur changeset" do + crowdsourced_slur = crowdsourced_slur_fixture() + assert %Ecto.Changeset{} = UserContribution.change_crowdsourced_slur(crowdsourced_slur) + end + end +end