Skip to content

Commit

Permalink
feat: revert draft
Browse files Browse the repository at this point in the history
  • Loading branch information
arpowers committed Sep 21, 2024
1 parent a2e4123 commit 3cdb320
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 11 deletions.
51 changes: 46 additions & 5 deletions @fiction/site/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ export type ManageSiteRequestParams =
| { _action: 'create', fields: Partial<TableSiteConfig> }
| { _action: 'update', where: WhereSite, fields: Partial<TableSiteConfig> }
| { _action: 'saveDraft', where: WhereSite, fields: Partial<TableSiteConfig> }
| { _action: 'revertDraft', where: WhereSite }
| { _action: 'delete', where: WhereSite }
| { _action: 'retrieve', where: WhereSite }

Expand Down Expand Up @@ -421,6 +422,9 @@ export class ManageSite extends SitesQuery {
case 'saveDraft':
result = await this.saveDraft(params, meta)
break
case 'revertDraft':
result = await this.revertDraft(params as ManageSiteParams & { _action: 'revertDraft' }, meta)
break
case 'delete':
result = await this.deleteSite(params as ManageSiteParams & { _action: 'delete' }, meta)
break
Expand Down Expand Up @@ -448,7 +452,7 @@ export class ManageSite extends SitesQuery {
const prepped = this.settings.fictionDb.prep({ type: 'insert', fields: mergedFields, table: t.sites, meta })

const [site] = await this.settings.fictionDb.client().insert({ orgId, userId, ...prepped }).into(t.sites).onConflict('site_id').ignore().returning<TableSiteConfig[]>('*')
this.log.info('creating site', { data: { fields: prepped, site } })

if (!site?.siteId)
throw abort('site not created')

Expand Down Expand Up @@ -513,7 +517,9 @@ export class ManageSite extends SitesQuery {

const draft = (currentDrafts?.draft || {}) as TableSiteConfig

const keysToRemove = ['draft', 'draftHistory', 'siteId', 'userId', 'orgId']
const draftPages = fields.pages || []

const keysToRemove = ['draft', 'draftHistory', 'siteId', 'userId', 'orgId', 'pages']

keysToRemove.forEach((key) => {
delete fields[key as keyof typeof fields]
Expand All @@ -528,16 +534,51 @@ export class ManageSite extends SitesQuery {
.update({ draft: JSON.stringify(newDraft) })
.returning<TableSiteConfig[]>('*')

if (fields.pages && fields.pages.length) {
await this.updateSitePages({ siteId: site.siteId, orgId, fields: fields.pages, userId, scope: 'draft' }, meta)
if (draftPages && draftPages.length) {
await this.updateSitePages({ siteId: site.siteId, orgId, fields: draftPages, userId, scope: 'draft' }, meta)
}

const r = await this.retrieveSite({ _action: 'retrieve', scope: 'draft', caller: 'saveDraft', where }, meta)
this.log.info('saveDraft', { data: { where, fields, newDraft, site: r.data } })

return { status: 'success', data: r.data }
}

private async revertDraft(params: ManageSiteParams & { _action: 'revertDraft' }, meta: EndpointMeta): Promise<EndpointResponse<TableSiteConfig>> {
const { where, orgId } = params
const db = this.settings.fictionDb.client()

const selector = await this.getSiteSelector(where)

// Revert site draft
const [updatedSite] = await db(t.sites)
.where({ orgId, ...selector })
.update({ draft: '{}' })
.returning('*')

if (!updatedSite) {
throw abort('Site not found')
}

// Revert page drafts
await db(t.pages)
.where({ siteId: updatedSite.siteId })
.update({ draft: '{}' })

// Fetch the updated site with reverted drafts
const result = await this.retrieveSite({
_action: 'retrieve',
where: { siteId: updatedSite.siteId },
orgId,
caller: 'revertDraft',
scope: 'publish', // Use 'publish' to get the site without draft data
}, meta)

return {
...result,
message: 'Site reverted successfully',
}
}

private async deleteSite(params: ManageSiteParams & { _action: 'delete' }, _meta: EndpointMeta): Promise<EndpointResponse<TableSiteConfig>> {
const { where, orgId } = params
const db = this.settings.fictionDb.client()
Expand Down
15 changes: 13 additions & 2 deletions @fiction/site/plugin-builder/SiteEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,19 @@ async function save() {
async function resetToPublished() {
if (!site.value)
throw new Error('No site to revert')
// await saveSiteDraft({ site: site.value, resetToPublished: true })
const s = site.value
const siteId = s.siteId
const r = await s.settings.fictionSites.requests.ManageSite.projectRequest({
_action: 'revertDraft',
where: { siteId },
caller: 'saveSite',
})
if (r.status === 'success') {
console.log('Reverted to published version', r)
await site.value.update({ ...r.data }, { noSave: true, caller: 'resetToPublished' })
}
}
</script>

Expand Down
2 changes: 1 addition & 1 deletion @fiction/site/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class Site<T extends SiteSettings = SiteSettings> extends FictionObject<T
pgs.push(...c.pages)
}

await this.update({ pages: pgs }, { caller: 'loadConfig' })
await this.update({ pages: pgs }, { caller: 'loadConfig', noSave: true })

this.sections.value = setSections({ site: this, themeSections: c.sections })

Expand Down
109 changes: 107 additions & 2 deletions @fiction/site/test/manageSite.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ describe('manageSite query', () => {
)

expect(response.status).toBe('success')
expect(response.data?.draft?.title).toBe('Draft Site Title')
expect(response.data?.draft?.userConfig?.draftKey).toBe('draftValue')
expect(response.data?.title).toBe('Draft Site Title')
expect(response.data?.userConfig?.draftKey).toBe('draftValue')
})

it('should retrieve a site with merged draft data when scope is draft', async () => {
Expand Down Expand Up @@ -343,6 +343,111 @@ describe('manageSite query', () => {
})
})

describe('site draft reversion', () => {
let siteId: string
let cardId: string

beforeEach(async () => {
const fields = createSiteFields('Draft Reversion Test Site')
const response = await testUtils.fictionSites.queries.ManageSite.run(
{ _action: 'create', fields, orgId, userId, caller: 'test' },
{ server: true },
)
siteId = response.data?.siteId as string
cardId = objectId({ prefix: 'card' })

// Add a published page to the site
await testUtils.fictionSites.queries.ManagePage.serve(
{
_action: 'upsert',
siteId,
fields: [{ cardId, templateId: 'wrap', title: 'Published Page', slug: 'published-page' }],
orgId,
userId,
caller: 'test',
scope: 'publish',
},
{ server: true },
)
})

it('should revert site and page drafts', async () => {
// Create drafts for site and page
const siteDraft = { title: 'Draft Site Title' }
const pageDraft = { cardId, templateId: 'wrap', title: 'Draft Page Title', slug: 'published-page' }

await testUtils.fictionSites.queries.ManageSite.serve(
{ _action: 'saveDraft', where: { siteId }, fields: siteDraft, orgId, userId, caller: 'test' },
{ server: true },
)

await testUtils.fictionSites.queries.ManagePage.serve(
{
_action: 'saveDraft',
siteId,
fields: [pageDraft],
orgId,
userId,
caller: 'test',
scope: 'draft',
},
{ server: true },
)

// Revert drafts
const revertResponse = await testUtils.fictionSites.queries.ManageSite.run(
{ _action: 'revertDraft', where: { siteId }, orgId, userId, caller: 'test' },
{ server: true },
)

expect(revertResponse.status).toBe('success')
expect(revertResponse.message).toMatchInlineSnapshot(`"Site reverted successfully"`)
expect(revertResponse.message).toBeTruthy()

// Verify site draft is reverted
const siteResponse = await testUtils.fictionSites.queries.ManageSite.run(
{ _action: 'retrieve', where: { siteId }, orgId, userId, caller: 'test', scope: 'draft' },
{ server: true },
)

expect(siteResponse.data?.title).not.toBe('Draft Site Title')

// Verify page draft is reverted
const pageResponse = await testUtils.fictionSites.queries.ManagePage.serve(
{
_action: 'retrieve',
where: [{ cardId }],
siteId,
orgId,
caller: 'test',
scope: 'draft',
},
{ server: true },
)

expect(pageResponse.data?.[0]?.title).toBe('Published Page')
})

it('should handle revert when no drafts exist', async () => {
const revertResponse = await testUtils.fictionSites.queries.ManageSite.run(
{ _action: 'revertDraft', where: { siteId }, orgId, userId, caller: 'test' },
{ server: true },
)

expect(revertResponse.status).toBe('success')
expect(revertResponse.message).toMatchInlineSnapshot(`"Site reverted successfully"`)
expect(revertResponse.message).toBeTruthy()
})

it('should throw an error when reverting non-existent site', async () => {
const nonExistentSiteId = objectId({ prefix: 'sit' })
await expect(testUtils.fictionSites.queries.ManageSite.run(
{ _action: 'revertDraft', where: { siteId: nonExistentSiteId }, orgId, userId, caller: 'test' },
{ server: true },
)).rejects.toThrowErrorMatchingInlineSnapshot(`[EndpointError: Site not found]`)
})
})

describe('edge cases and error handling', () => {
it('should have correct error message for invalid theme', async () => {
const fields = { ...createSiteFields('Invalid Theme Site'), themeId: 'non-existent-theme' }
Expand Down
2 changes: 1 addition & 1 deletion @fiction/site/utils/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export async function updateSite(args: { site: Site, newConfig: Partial<SiteSett
if (sections)
site.sections.value = setSections({ site, sections })

// site.syncChange({ caller, noSave })
site.syncChange({ caller, noSave })

return site
}
Expand Down

0 comments on commit 3cdb320

Please sign in to comment.