Skip to content

Commit

Permalink
padawan - bill creator organizations errors, set default support as For
Browse files Browse the repository at this point in the history
  • Loading branch information
dcordz committed Dec 11, 2024
1 parent db7b3d2 commit 8d7ac28
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 60 deletions.
51 changes: 42 additions & 9 deletions app/controllers/organizations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@ def show
end

def create
organizations_params[:organizations].each do |param|
organization = find_organization_from_param(param)
errored = false
errors = {
organizations: organizations_params[:organizations].map do |_|
{
label: nil,
value: nil,
summary: nil,
support: nil,
icon_path: nil
}
end
}

organizations_params[:organizations].each_with_index do |param, index|
organization = find_or_initialize_organization_from_param(param)
current_icon_path = organization.icon_path.freeze
organization.icon_path = param[:icon_path]

Expand All @@ -35,16 +48,36 @@ def create
position.support = param[:support]
position.summary = param[:summary]

begin
position.save!
rescue Exception => e # rubocop:disable Lint/RescueException
Rails.logger.error(e)
Sentry.capture_exception(e)
unless position.save
errored = true
position.errors.each do |e|
if errors[:organizations][index].key?(e.attribute)
errors[:organizations][index][e.attribute] = "#{e.attribute.capitalize} #{e.message}"
end
end
end
else
errored = true
organization.errors.each do |e|
attribute_by_key = {
name: :label,
id: :value,
icon_path: :icon_path
}

attr = attribute_by_key[e.attribute]
if attr.present? && errors[:organizations][index].key?(attr)
errors[:organizations][index][attr] = "#{attr} #{e.message.capitalize}"
end
end
end
end

redirect_to edit_bill_path(@bill.id, {saved: "Supporting/Opposing Arguments Saved", event_key: "organizations"})
if errored
redirect_to edit_bill_path(@bill.id, {event_key: "organizations"}), inertia: {errors: errors}
else
redirect_to edit_bill_path(@bill.id, {saved: "Supporting/Opposing Arguments Saved", event_key: "organizations"})
end
end

private
Expand All @@ -57,7 +90,7 @@ def organizations_params
params.permit(:bill_id, organizations: %i[label value summary support icon_path])
end

def find_organization_from_param(param)
def find_or_initialize_organization_from_param(param)
o = param[:value].blank? ? nil : Organization.find_by(id: param[:value]).presence
o || Organization.find_or_initialize_by(name: param[:label], sway_locale: @bill.sway_locale)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const BillCreatorAccordions: React.FC<IProps> = ({ setCreatorDirty }) => {
</AccordionButton>

<Accordion.Body>
<BillCreatorOrganizations error={""} />
<BillCreatorOrganizations />
</Accordion.Body>
</Accordion.Item>
</Accordion>
Expand Down
13 changes: 10 additions & 3 deletions app/frontend/components/admin/creator/BillCreatorOrganization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { Button, Form } from "react-bootstrap";
import { sway } from "sway";

import { Divider } from "@mui/material";
import { ICreatorOrganizations, TOrganizationOption } from "app/frontend/components/admin/creator/types";
import {
ICreatorOrganizations,
TOrganizationError,
TOrganizationOption,
} from "app/frontend/components/admin/creator/types";
import { useFormContext } from "app/frontend/components/contexts/hooks/useFormContext";
import FullScreenLoading from "app/frontend/components/dialogs/FullScreenLoading";
import OrganizationIcon from "app/frontend/components/organizations/OrganizationIcon";
Expand All @@ -18,7 +22,7 @@ const FileUploadModal = lazy(() => import("app/frontend/components/dialogs/FileU
interface IProps {
index: number;
organization: TOrganizationOption;
error: string;
error: TOrganizationError | undefined;
}

const BillCreatorOrganization: React.FC<IProps> = ({ index, organization, error }) => {
Expand All @@ -44,6 +48,7 @@ const BillCreatorOrganization: React.FC<IProps> = ({ index, organization, error
<div className="col my-2">
<div className="row align-items-center justify-content-center">
<h3>{organization.label}</h3>
{error?.label && <div className="text-danger">{error.label}</div>}
</div>
<div className="row align-items-center justify-content-center">
<div className="col-6">
Expand All @@ -60,6 +65,7 @@ const BillCreatorOrganization: React.FC<IProps> = ({ index, organization, error
}
label={titleize(support === Support.For ? Support.For : Support.Against)}
/>
{error?.support && <div className="text-danger">{error.support}</div>}
</Form.Group>
</div>
<div className="col-6">
Expand All @@ -75,6 +81,7 @@ const BillCreatorOrganization: React.FC<IProps> = ({ index, organization, error
Add Icon <FiPlus />
</Button>
)}
{error?.icon_path && <div className="text-danger">{error.icon_path}</div>}
</div>
</div>
<Divider className="my-5" />
Expand All @@ -90,7 +97,7 @@ const BillCreatorOrganization: React.FC<IProps> = ({ index, organization, error
isRequired: true,
}}
value={summary}
error={error}
error={error?.summary}
helperText={`${organization.label} opinion of bill.`}
/>
</div>
Expand Down
27 changes: 18 additions & 9 deletions app/frontend/components/admin/creator/BillCreatorOrganizations.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
/** @format */

import { usePage } from "@inertiajs/react";

import BillCreatorFormHeader from "app/frontend/components/admin/creator/BillCreatorFormHeader";
import { useTempStorage } from "app/frontend/components/admin/creator/hooks/useTempStorage";
import { ICreatorOrganizations, TOrganizationOption } from "app/frontend/components/admin/creator/types";
import {
ICreatorOrganizations,
IOrganizationErrors,
TOrganizationError,
TOrganizationOption,
} from "app/frontend/components/admin/creator/types";
import FormContext from "app/frontend/components/contexts/FormContext";
import { useSearchParams } from "app/frontend/hooks/useSearchParams";
import { Support } from "app/frontend/sway_constants";
Expand All @@ -17,20 +23,19 @@ import { useInertiaForm } from "use-inertia-form";
import { notify, REACT_SELECT_STYLES, SWAY_STORAGE } from "../../../sway_utils";
import BillCreatorOrganization from "./BillCreatorOrganization";

interface IProps {
error: string | undefined;
}

const toCreatorOption = (organization: sway.IOrganization, billId: number) =>
({
value: organization.id,
label: organization.name,
summary: organization.positions?.find((p) => p.billId === billId)?.summary,
support: organization.positions?.find((p) => p.billId === billId)?.support,
support: organization.positions?.find((p) => p.billId === billId)?.support ?? Support.For,
icon_path: organization.iconPath,
}) as TOrganizationOption;

const BillCreatorOrganizations: React.FC<IProps> = ({ error }) => {
const BillCreatorOrganizations: React.FC = () => {
// @ts-expect-error - Property 'organizations' is missing in type 'Errors & ErrorBag' but required in type 'IOrganizationErrors'.
const errors: IOrganizationErrors = usePage().props.errors;

const bill = usePage().props.bill as sway.IBill & { organizations: sway.IOrganization[] };
const organizations = usePage().props.organizations as sway.IOrganization[];
const billOrganizations = bill.organizations as sway.IOrganization[];
Expand Down Expand Up @@ -84,13 +89,17 @@ const BillCreatorOrganizations: React.FC<IProps> = ({ error }) => {

return (
<Fragment key={`${organization.label}-${index}`}>
<BillCreatorOrganization index={index} organization={organization} error={error || ""} />
<BillCreatorOrganization
index={index}
organization={organization}
error={errors?.organizations?.[index] as TOrganizationError | undefined}
/>
{isLastOrganization ? null : <hr />}
</Fragment>
);
},
),
[data.organizations, error],
[data.organizations, errors],
);

const handleCreateOption = useCallback(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { usePage } from "@inertiajs/react";
import { IApiBillCreator } from "app/frontend/components/admin/creator/types";
import { TempBillStorage } from "app/frontend/components/bill/creator/TempBillStorage";
import { useLocale } from "app/frontend/hooks/useLocales";
import { parseISO } from "date-fns";

export const useNewBillInitialValues = (): IApiBillCreator => {
const [locale] = useLocale();
Expand All @@ -36,10 +35,10 @@ export const useNewBillInitialValues = (): IApiBillCreator => {
status: bill?.status?.trim() ?? "",
active: typeof bill?.active === "boolean" ? bill.active : true,

introduced_date_time_utc: bill?.introducedDateTimeUtc ? parseISO(bill?.introducedDateTimeUtc) : null,
withdrawn_date_time_utc: bill?.withdrawnDateTimeUtc ? parseISO(bill?.withdrawnDateTimeUtc) : null,
house_vote_date_time_utc: bill?.houseVoteDateTimeUtc ? parseISO(bill?.houseVoteDateTimeUtc) : null,
senate_vote_date_time_utc: bill?.senateVoteDateTimeUtc ? parseISO(bill?.senateVoteDateTimeUtc) : null,
introduced_date_time_utc: bill?.introducedDateTimeUtc ? new Date(bill?.introducedDateTimeUtc) : null,
withdrawn_date_time_utc: bill?.withdrawnDateTimeUtc ? new Date(bill?.withdrawnDateTimeUtc) : null,
house_vote_date_time_utc: bill?.houseVoteDateTimeUtc ? new Date(bill?.houseVoteDateTimeUtc) : null,
senate_vote_date_time_utc: bill?.senateVoteDateTimeUtc ? new Date(bill?.senateVoteDateTimeUtc) : null,

sway_locale_id: locale.id,

Expand Down
7 changes: 6 additions & 1 deletion app/frontend/components/admin/creator/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ISelectOption, sway } from "sway";
import { ISelectOption, KeyOf, sway } from "sway";

export interface IFieldProps<T> {
swayField: sway.IFormField<T>;
Expand Down Expand Up @@ -28,6 +28,11 @@ export interface ICreatorLegislatorVotes {

export type TOrganizationOption = ISelectOption & { summary: string; support: sway.TUserSupport; icon_path?: string };

export type TOrganizationError = Record<KeyOf<TOrganizationOption>, string> | undefined;
export interface IOrganizationErrors {
organizations: TOrganizationError[];
}

export interface ICreatorOrganizations {
bill_id: number;
organizations: TOrganizationOption[];
Expand Down
7 changes: 6 additions & 1 deletion app/frontend/entrypoints/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ document.addEventListener("DOMContentLoaded", () => {
InertiaProgress.init();

createInertiaApp({
resolve: async (pageName: string) => {
resolve: async (_pageName: string) => {
let pageName = _pageName;
if (!pageName) {
pageName = "Home";
}

logDev("index.tsx - createInertiaApp - page pageName -", pageName);

const LayoutComponent = NO_AUTH_LAYOUTS.includes(pageName.toLowerCase()) ? NoAuthLayout : LayoutWithPage;
Expand Down
2 changes: 2 additions & 0 deletions app/models/organization_bill_position.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class OrganizationBillPosition < ApplicationRecord

validates :bill_id, uniqueness: {scope: :organization_id, allow_nil: true}

validates :support, :summary, :organization, :bill, presence: {message: "can't be blank"}

sig { returns(Bill) }
def bill
T.cast(super, Bill)
Expand Down
3 changes: 3 additions & 0 deletions bin/docker-entrypoint
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

# echo "docker-entrypoint.sh -> Setting up New Relic"

echo "docker-entrypoint.sh SENTRY_ORG -> $SENTRY_ORG"
echo "docker-entrypoint.sh SENTRY_PROJECT -> $SENTRY_PROJECT"

echo "docker-entrypoint.sh -> Copying files to volume"
./bin/rake sway:volume_setup

Expand Down
8 changes: 2 additions & 6 deletions db/seeds/models/bill.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@ class SeedBill

sig { params(sway_locales: T::Array[SwayLocale]).void }
def self.run(sway_locales)
return nil unless Rails.env.development?

sway_locales.each do |sway_locale|
T.let(read_bills(sway_locale), T::Array[T::Hash[String, String]]).each do |json|
j = T.let(json, T::Hash[String, String])
if j["test"]
if Rails.env.production?
Bill.find_by(external_id: j["external_id"])&.destroy
elsif j.fetch("external_id", nil).present?
SeedBill.new.seed(j, sway_locale)
end
elsif j.fetch("external_id", nil).present?
SeedBill.new.seed(j, sway_locale)
end
end
Expand Down
9 changes: 8 additions & 1 deletion docker/dockerfiles/production.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@ LABEL fly_launch_runtime="rails"
WORKDIR /rails

# Set production environment
ARG SENTRY_AUTH_TOKEN="" \
SENTRY_ORG="sway-a6" \
SENTRY_PROJECT="sway"

ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development:test"
BUNDLE_WITHOUT="development:test" \
SENTRY_AUTH_TOKEN="$SENTRY_AUTH_TOKEN" \
SENTRY_ORG="$SENTRY_ORG" \
SENTRY_PROJECT="$SENTRY_PROJECT"


# Throw-away build stage to reduce size of final image
Expand Down
6 changes: 4 additions & 2 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env zsh

export $(cat .env.github | xargs)
export $(cat .env.production | xargs)

echo "deploy.sh -> RAILS_ENV=production bundle install"
Expand Down Expand Up @@ -43,7 +42,10 @@ else
--platform linux/amd64 \
-t ghcr.io/plebeian-technology/sway:latest \
--compress \
--push
--push \
--build-arg SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN \
--build-arg SENTRY_ORG=$SENTRY_ORG \
--build-arg SENTRY_PROJECT=$SENTRY_PROJECT

fly deploy
fi
15 changes: 12 additions & 3 deletions vite.config.build.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { sentryVitePlugin } from "@sentry/vite-plugin";
import { defineConfig } from "vite";
// import RubyPlugin from "vite-plugin-ruby"
import RailsPlugin from "vite-plugin-rails";
import ReactPlugin from "@vitejs/plugin-react";
import { readFileSync } from "fs";
import { resolve } from "path";
import RailsPlugin from "vite-plugin-rails";
import console from "console";

export default defineConfig({
plugins: [RailsPlugin(), ReactPlugin()],
plugins: [
RailsPlugin(),
ReactPlugin(),
sentryVitePlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
}),
],

resolve: {
alias: {
Expand Down
9 changes: 5 additions & 4 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ export default defineConfig({
plugins: [
RailsPlugin(),
ReactPlugin(),
sentryVitePlugin({
org: "sway-a6",
project: "sway",
}),
// sentryVitePlugin({
// authToken: process.env.SENTRY_AUTH_TOKEN,
// org: "sway-a6",
// project: "sway",
// }),
],

server: {
Expand Down

0 comments on commit 8d7ac28

Please sign in to comment.