Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate(tags): delete tags with isBulkImport & delete column #3533

Merged
merged 2 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 42 additions & 55 deletions adminSiteClient/TagEditPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ interface TagPageData {
charts: ChartListItem[]
children: DbChartTagJoin[]
possibleParents: DbChartTagJoin[]
isBulkImport: boolean
slug: string | null
}

Expand Down Expand Up @@ -140,67 +139,55 @@ class TagEditor extends React.Component<{ tag: TagPageData }> {
}}
>
<BindString
disabled={tag.isBulkImport}
field="name"
store={newtag}
label="Name"
helpText="Category names should ideally be unique across the database and able to be understood without context"
/>
{!tag.isBulkImport && (
<>
<BindString
field="slug"
store={newtag}
label="Slug"
helpText="The slug for this tag's topic page, e.g. trade-and-globalization. If specified, we assume this tag is a topic."
/>
<FieldsRow>
<NumericSelectField
label="Parent Category"
value={newtag.parentId || -1}
options={[
{ value: -1, label: "None" },
].concat(
tag.possibleParents.map((p) => ({
value: p.id as number,
label: p.name,
}))
)}
onValue={this.onChooseParent}
/>
<div>
<br />
{this.parentTag && (
<TagBadge
tag={
this
.parentTag as DbChartTagJoin
}
/>
)}
</div>
</FieldsRow>
</>
)}
{!tag.isBulkImport && (
<BindString
field="slug"
store={newtag}
label="Slug"
helpText="The slug for this tag's topic page, e.g. trade-and-globalization. If specified, we assume this tag is a topic."
/>
<FieldsRow>
<NumericSelectField
label="Parent Category"
value={newtag.parentId || -1}
options={[{ value: -1, label: "None" }].concat(
tag.possibleParents.map((p) => ({
value: p.id as number,
label: p.name,
}))
)}
onValue={this.onChooseParent}
/>
<div>
<input
type="submit"
className="btn btn-success"
value="Update category"
/>{" "}
{tag.datasets.length === 0 &&
tag.children.length === 0 &&
!tag.specialType && (
<button
className="btn btn-danger"
onClick={() => this.deleteTag()}
>
Delete category
</button>
)}
<br />
{this.parentTag && (
<TagBadge
tag={this.parentTag as DbChartTagJoin}
/>
)}
</div>
)}
</FieldsRow>
<div>
<input
type="submit"
className="btn btn-success"
value="Update category"
/>{" "}
{tag.datasets.length === 0 &&
tag.children.length === 0 &&
!tag.specialType && (
<button
className="btn btn-danger"
onClick={() => this.deleteTag()}
>
Delete category
</button>
)}
</div>
</form>
</section>
{tag.children.length > 0 && (
Expand Down
7 changes: 2 additions & 5 deletions adminSiteServer/apiRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,6 @@ getRouteWithROTransaction(
SELECT t.id, t.name, p.name AS parentName
FROM tags AS t
JOIN tags AS p ON t.parentId=p.id
WHERE p.isBulkImport IS FALSE
`
)
dataset.availableTags = availableTags
Expand Down Expand Up @@ -1844,12 +1843,11 @@ getRouteWithROTransaction(
| "updatedAt"
| "parentId"
| "slug"
| "isBulkImport"
>
>(
trx,
`-- sql
SELECT t.id, t.name, t.specialType, t.updatedAt, t.parentId, t.slug, p.isBulkImport
SELECT t.id, t.name, t.specialType, t.updatedAt, t.parentId, t.slug
FROM tags t LEFT JOIN tags p ON t.parentId=p.id
WHERE t.id = ?
`,
Expand Down Expand Up @@ -1958,7 +1956,7 @@ getRouteWithROTransaction(
trx,
`-- sql
SELECT t.id, t.name FROM tags t
WHERE t.parentId IS NULL AND t.isBulkImport IS FALSE
WHERE t.parentId IS NULL
`
)
tag.possibleParents = possibleParents
Expand Down Expand Up @@ -2028,7 +2026,6 @@ getRouteWithROTransaction(apiRouter, "/tags.json", async (req, res, trx) => {
`-- sql
SELECT t.id, t.name, t.parentId, t.specialType
FROM tags t LEFT JOIN tags p ON t.parentId=p.id
WHERE t.isBulkImport IS FALSE AND (t.parentId IS NULL OR p.isBulkImport IS FALSE)
ORDER BY t.name ASC
`
)
Expand Down
36 changes: 36 additions & 0 deletions db/migration/1713987607342-RemoveTagsBulkImport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { MigrationInterface, QueryRunner } from "typeorm"

export class RemoveTagsBulkImport1713987607342 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
// We need to run this query twice: There's a tags.parentId -> tags.id
// relation that we need to break in two steps; first deleting all the
// leaf tags, and then deleting those that used to be a parent but are
// now child-less.
for (let i = 0; i <= 1; i++) {
// Only delete those tags that are not the parent of any other tag
// - i.e. leaf tags.
await queryRunner.query(`-- sql
WITH leaf_tags AS (
SELECT t.id, t.name
FROM tags t
WHERE t.id NOT IN (
SELECT parentId FROM tags WHERE parentId IS NOT NULL
))
DELETE
FROM tags
WHERE isBulkImport = 1
and id IN (SELECT id FROM leaf_tags)
`)
}

await queryRunner.query(`-- sql
ALTER TABLE tags DROP COLUMN isBulkImport
`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`-- sql
ALTER TABLE tags ADD COLUMN isBulkImport TINYINT(1) NOT NULL DEFAULT 0
`)
}
}
1 change: 0 additions & 1 deletion packages/@ourworldindata/types/src/dbTypes/Tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export const TagsTableName = "tags"
export interface DbInsertTag {
createdAt?: Date
id?: number
isBulkImport?: number
name: string
parentId?: number | null
slug?: string | null
Expand Down