Skip to content

Commit

Permalink
Enable CSV export
Browse files Browse the repository at this point in the history
  • Loading branch information
nygrenh committed Aug 30, 2024
1 parent 7fe5568 commit 7a3dc8f
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@ CREATE TABLE code_giveaway_codes (
code_giveaway_id UUID NOT NULL REFERENCES code_giveaways(id),
code_given_to_user_id UUID REFERENCES users(id),
added_by_user_id UUID NOT NULL REFERENCES users(id),
code VARCHAR(2048) NOT NULL
code VARCHAR(2048) NOT NULL,
-- No duplicate codes in a giveaway
UNIQUE NULLS NOT DISTINCT (code_giveaway_id, code, deleted_at)
);
-- A user can only receive one code from a giveaway. We use unique index here because if we used a unique constraint we would like to have NULLS NOT disctinct on the delted_at column but NULLS DISTINCT on the code_given_to_user_id column. This did not seem possible so we use a unique index instead.
CREATE UNIQUE INDEX giveaway_codes_one_code_per_user ON code_giveaway_codes (code_giveaway_id, code_given_to_user_id)
WHERE deleted_at IS NULL;


CREATE TRIGGER set_timestamp BEFORE
UPDATE ON code_giveaway_codes FOR EACH ROW EXECUTE PROCEDURE trigger_set_timestamp();
COMMENT ON TABLE code_giveaway_codes IS 'A code that is available in a code giveaway. A user can only receive one code from a giveaway.';
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions services/headless-lms/models/src/code_giveaway_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub async fn insert_many(

query_builder.push_values(input, |mut b, code| {
b.push_bind(code_giveaway_id)
.push_bind(code)
.push_bind(code.trim())
.push_bind(added_by_user_id);
});

Expand Down Expand Up @@ -145,7 +145,7 @@ RETURNING *
Ok(res)
}

pub async fn stream_code_giveaway_codes<'a>(
pub async fn stream_given_code_giveaway_codes<'a>(
conn: &'a mut PgConnection,
code_giveaway_id: Uuid,
) -> impl Stream<Item = sqlx::Result<CodeGiveawayCode>> + 'a {
Expand All @@ -156,6 +156,7 @@ SELECT *
FROM code_giveaway_codes
WHERE code_giveaway_id = $1
AND deleted_at IS NULL
AND code_given_to_user_id IS NOT NULL
"#,
code_giveaway_id
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ where
"code".to_string(),
]);

let mut stream = code_giveaway_codes::stream_code_giveaway_codes(conn, code_giveaway_id).await;
let mut stream =
code_giveaway_codes::stream_given_code_giveaway_codes(conn, code_giveaway_id).await;

let writer = CsvWriter::new_with_initialized_headers(writer, headers).await?;
while let Some(next) = stream.try_next().await? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const NewCodeGiveawayForm: React.FC<NewCodeGiveawayFormProps> = ({
}) => {
const [name, setName] = useState("")

const valid = useMemo(() => name.trim() === "", [name])
const valid = useMemo(() => name.trim() !== "", [name])
const { t } = useTranslation()

const createCodeGiveawayMutation = useToastMutation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ import ErrorBanner from "@/shared-module/common/components/ErrorBanner"
import Spinner from "@/shared-module/common/components/Spinner"
import { baseTheme, headingFont, typography } from "@/shared-module/common/styles"

const CodesWrapper = styled.div`
margin: 2rem 0;
`

const CodeGiveawayPage = () => {
const router = useRouter()
const { id } = router.query
Expand Down Expand Up @@ -61,16 +57,26 @@ const CodeGiveawayPage = () => {
{t("heading-code-giveaway-name", { name: codeGiveawayQuery.data?.name ?? "" })}
</h1>

<Button
size="medium"
variant="primary"
onClick={() => setRevealCodes(!revealCodes)}
<div
className={css`
margin-top: 1rem;
`}
>
{t(revealCodes ? "hide" : "reveal")}
</Button>
<Button size="medium" variant="primary" onClick={() => setRevealCodes(!revealCodes)}>
{t(revealCodes ? "hide" : "reveal")}
</Button>
<a href={`/api/v0/main-frontend/code-giveaways/${id}/codes/csv`} download>
<Button
size="medium"
variant="primary"
className={css`
margin-top: 1rem;
`}
>
{t("link-export-given-codes-as-csv")}
</Button>
</a>
</div>
<FullWidthTable>
<thead>
<FullWidthTableRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
"link-course-instances": "Course instances",
"link-edit-exam-instructions": "Edit exam instructions",
"link-exercises": "Exercises",
"link-export-given-codes-as-csv": "Export given codes as CSV",
"link-export-completions": "Export completions as CSV",
"link-export-course-instances": "Export course instances as CSV",
"link-export-course-user-consents": "Export course research consent form answers as CSV",
Expand Down

0 comments on commit 7a3dc8f

Please sign in to comment.