Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
2632484
Add API logic to publish bill XML
May 5, 2025
e59fbbd
Add publishDocument
May 5, 2025
3808a7a
Export API to publish bill
May 5, 2025
b0f3a2e
Add publishDocument
May 5, 2025
daf4338
Add translation for publishing bill
May 5, 2025
f1dada6
Fix selection of bill
May 5, 2025
d6e1b38
Fix indent
May 5, 2025
d7502ee
Fix indent
May 5, 2025
04e08ed
Fix indent
May 5, 2025
7694090
Fix indent
May 5, 2025
75ea422
Fix indent
May 5, 2025
5288970
Load ContentType
May 5, 2025
2372bc5
Log more detail
May 5, 2025
bf45c1e
Fix indent, await, content-type
May 5, 2025
2125dcb
Remove async() for now
May 5, 2025
4b138cc
Fix indent, remove arguments not needed
May 5, 2025
679fd82
Remove arguments not needed
May 5, 2025
faa6e31
Fix lint
May 5, 2025
fb3b416
Correct URL to validation endpoint
May 5, 2025
4382530
Auto-generated update
May 6, 2025
fb7a429
Rename publishDocument() to publishBill()
May 6, 2025
464bf60
Use XML headers by default
May 6, 2025
3afdbca
Update definition of publishXml()
May 6, 2025
409ba5f
Add logic to publish bill
May 6, 2025
7a47190
Updated comment
May 6, 2025
47dd2cb
Catch error, parse and re-throw
May 8, 2025
67b622a
Catch any errors, re-throw using HttpError()
May 8, 2025
3b4c76f
Fix lint
May 8, 2025
523030c
Hide publish button when document is not saved
May 9, 2025
ac30a18
Add notification about bill being published
May 9, 2025
37414ca
Fix indent
May 9, 2025
45c9df8
Fix indent
May 9, 2025
5b23e9a
Fix lint
May 9, 2025
12b370b
Force type
May 9, 2025
b77125f
Stop including exportXml, not needed
May 9, 2025
31cd857
Add t() to dependency array
May 9, 2025
b839fc9
Fix indent
May 9, 2025
e50d272
Remove exportXml from imports, not used
May 9, 2025
3f79bfc
Remove references to handlePublish & implementation
May 12, 2025
8729793
Update turbo.json
gudmdharalds May 12, 2025
edc1410
Update turbo.json
gudmdharalds May 12, 2025
54030c9
Publish all documents that compose bill
May 13, 2025
52cf906
Merge branch 'add/publish-bills-2025a' of github.com:althingi-net/edi…
May 13, 2025
d8e46bc
Update API endpoint paths
May 15, 2025
d42290d
Merge branch 'develop' into add/publish-bills-2025a
gudmdharalds May 20, 2025
5b335a9
Update useBillPage.ts
gudmdharalds May 21, 2025
61123f8
Merge branch 'add/publish-bills-2025a' of github.com:althingi-net/edi…
May 21, 2025
bb3ff0d
Update strings & translations
May 21, 2025
2fa9762
Fix new entry modal having correct title
ch1ll0ut1 May 27, 2025
75404ce
Remove unnecessary boolean conversion
ch1ll0ut1 May 27, 2025
fec31fb
Revert removal of translation for "Add Entry"
ch1ll0ut1 May 27, 2025
5e9c1cd
Change setting axios headers from globally to locally
ch1ll0ut1 May 27, 2025
f7c7cc6
Fix some minor syntax in lagasafnApi file
ch1ll0ut1 May 27, 2025
f9fad7c
.
ch1ll0ut1 May 27, 2025
896c9ba
Fix tests of DocumentService
ch1ll0ut1 May 27, 2025
1238a45
Remove error in case external api is unavailable
ch1ll0ut1 May 27, 2025
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
18 changes: 18 additions & 0 deletions client-sdk/src/services/BillService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,22 @@ export class BillService {
},
});
}
/**
* Publish xml
* Publish bill XML
* @param id
* @returns any Successful response
* @throws ApiError
*/
public static billControllerPublishXml(
id: number,
): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/bills/{id}/xml',
path: {
'id': id,
},
});
}
}
4 changes: 2 additions & 2 deletions client/src/features/Bills/CreateBillButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const CreateBillButton: FC<Props> = ({ onSubmit }) => {
>
<PlusOutlined /> {t('Create New Bill')}
</Button>
<Modal title={t('Add new Entry')} isOpen={isOpen} onClose={onClose}>
<Modal title={t('Create New Bill')} isOpen={isOpen} onClose={onClose}>
<div>
<CreateBillForm onSubmit={onClose} onCancel={onClose} />
</div>
Expand All @@ -34,4 +34,4 @@ const CreateBillButton: FC<Props> = ({ onSubmit }) => {
);
};

export default CreateBillButton;
export default CreateBillButton;
25 changes: 23 additions & 2 deletions client/src/features/Bills/useBillPage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { notification } from 'antd';
import { BillDocumentService, DocumentService } from 'client-sdk';
import { BillDocumentService, DocumentService, BillService } from 'client-sdk';
import { LawEditor, getTitle } from 'law-document';
import { useCallback, useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router';
Expand Down Expand Up @@ -146,6 +146,26 @@ const useBillPage = (disableActions = false, billPage = '/bill') => {

useEffect(loadDocument, [loadDocument]);

const publishBill = useCallback(() => {
if (!bill || !bill.id || !selected) {
return;
}

log('publish bill document', { bill, selected });

BillService.billControllerPublishXml(bill.id)
.then((billItem) => {
notification.success({ message: t('Bill published'), description: `${selected} ${bill.title}` });
log('published bill', { billItem });
setError(false);
})
.catch((error) => {
log('Error publishing bill');
setError(true);
console.error(error);
});
}, [bill, selected, t]);

return {
bill,
openDocument,
Expand All @@ -158,10 +178,11 @@ const useBillPage = (disableActions = false, billPage = '/bill') => {
slate,
originalDocument,
loadDocument,
publishBill,
hasBillLoadingError: hasBillError,
hasDocumentLoadingError: hasError,
importError,
};
};

export default useBillPage;
export default useBillPage;
4 changes: 3 additions & 1 deletion client/src/pages/BillPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const BillPage: FC = () => {
xml,
originalDocument,
saveDocument,
publishBill,
hasBillLoadingError,
hasDocumentLoadingError,
isBillDocument,
Expand Down Expand Up @@ -80,6 +81,7 @@ const BillPage: FC = () => {
originalDocument={originalDocument!}
xml={xml!}
saveDocument={saveDocument}
publishBill={publishBill}
readOnly={!isBillDocument}
bill={bill}
t={t}
Expand All @@ -98,4 +100,4 @@ const BillPage: FC = () => {
);
};

export default BillPage;
export default BillPage;
7 changes: 4 additions & 3 deletions law-document-editor/src/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ interface Props {
xml: string;
readOnly?: boolean;
saveDocument?: (editor: LawEditor) => void;
publishBill?: () => void;
bill?: Bill;
navigationBlocker: NavigationBlocker;
t: Translator;
}

export const Editor: FC<Props> = (props) => {
const { slate, originalDocument, xml, readOnly, saveDocument, bill, navigationBlocker, t } = props;
const { slate, originalDocument, xml, readOnly, saveDocument, publishBill, bill, navigationBlocker, t } = props;
const hasHighlight = useEditorConfig(state => state.highlightStructure);
const editor = useMemo(() => createEditor(), []);
const { handleChange, handleSave } = useEditorNavigationBlock(editor, navigationBlocker, saveDocument);
Expand Down Expand Up @@ -71,7 +72,7 @@ export const Editor: FC<Props> = (props) => {
</div>
</Col>
<Col span={12}>
{ readOnly ? null : <Toolbar saveDocument={handleSave} bill={bill} t={t} navigationBlocker={navigationBlocker} /> }
{ readOnly ? null : <Toolbar saveDocument={handleSave} publishBill={publishBill} bill={bill} t={t} navigationBlocker={navigationBlocker} /> }
<EditorSidePanel
t={t}
readOnly={readOnly}
Expand All @@ -83,4 +84,4 @@ export const Editor: FC<Props> = (props) => {
</div>
</Slate>
);
};
};
2 changes: 1 addition & 1 deletion law-document-editor/src/Editor/Toolbar/AddEntryModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export const AddEntryModal: FC<Props> = ({ isOpen, onClose, t }) => {
</div>
</Modal>
);
};
};
6 changes: 4 additions & 2 deletions law-document-editor/src/Editor/Toolbar/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import { Translator } from '../../translations';

interface Props {
saveDocument?: (editor: LawEditor) => void;
publishBill?: (editor: LawEditor) => void;
bill?: Bill;
t: Translator;
navigationBlocker: NavigationBlocker;
}

export const Toolbar: FC<Props> = ({ saveDocument, bill, t, navigationBlocker }) => {
export const Toolbar: FC<Props> = ({ saveDocument, publishBill, bill, t, navigationBlocker }) => {
const {
setAutoNumberIncrements,
setHighlightStructure,
Expand All @@ -34,6 +35,7 @@ export const Toolbar: FC<Props> = ({ saveDocument, bill, t, navigationBlocker })
</Checkbox>
{saveDocument && <Button type={isNavigationBlocked ? 'primary' : 'default'} disabled={!isNavigationBlocked} onClick={() => saveDocument(slate)}>{t('Save')}</Button>}
{bill && <Button onClick={() => goTo(`/bill/${bill.id}`)}>{t('Open Bill Preview')}</Button>}
{publishBill && <Button onClick={() => publishBill(slate) } disabled={isNavigationBlocked}>{t('Publish Bill')}</Button>}
</Space>
);
};
};
2 changes: 1 addition & 1 deletion law-document-editor/src/Editor/useEditorNaviationBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ export const useEditorNavigationBlock = (editor: LawEditor, navigationBlocker: N
handleChange,
handleSave,
};
};
};
6 changes: 4 additions & 2 deletions law-document/src/slate/config/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const translations: { [key: string]: { [key: string]: string } } = {
'Documents in the Bill': 'Skjöl í frumvarpi',
'Add document to bill and start editing': 'Bæta við skjali í frumvarp og byrja að breyta',
'Remove document from bill and delete changes': 'Fjarlægja skjal úr frumvarpi og eyða breytingum',
'Create New Bill': 'Búa til nýtt frumvarp',
'Create New Bill': 'Stofna nýtt frumvarp',
'Delete Bill Document': 'Eyða skjali',
'Are you sure you want to permanently and irreversibly delete this document?': 'Ertu viss um að þú viljir eyða þessu skjali varanlega og óafturkræft?',
'Yes, delete!': 'Já, eyða!',
Expand All @@ -92,5 +92,7 @@ export const translations: { [key: string]: { [key: string]: string } } = {
'Open Bill Preview': 'Opna frumvarpsyfirlit',
'This bill is still empty!': 'Þetta frumvarp er enn tómt!',
'Tip: Start editing this bill by adding a document to it.': 'Ábending: Byrjaðu á að breyta þessu frumvarpi með því að bæta við skjali í það.',
'Publish Bill': 'Birta frumvarp',
'Bill published': 'Frumvarp hefur verið birt',
},
};
};
44 changes: 42 additions & 2 deletions server/src/controllers/BillController.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import passport from 'koa-passport';
import { Body, Get, JsonController, Param, Post, Put, UseBefore } from 'routing-controllers';
import { Body, Get, JsonController, Param, Post, Put, UseBefore, ContentType, HttpError } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { exportBillXml } from 'law-document';
import Bill from '../entities/Bill';
import BillDocument from '../entities/BillDocument';
import { postBillForValidation, postBillForPublishing } from '../integration/lagasafnApi';

@JsonController()
@OpenAPI({
Expand Down Expand Up @@ -39,6 +40,45 @@ class BillController {
return Bill.save(bill);
}

@Post('/bills/:id/xml')
@ContentType('text/xml')
@OpenAPI({
description: 'Publish bill XML',
})
async publishXml(
@Param('id') id: number,
) {
const bills = await Bill.find({ where: { id } });

if ( bills.length < 1 || ! bills[0]?.documents ) {
throw new HttpError( 404, 'Unable to find bill documents');
}

const billsXml: string[] = [];

bills[0].documents.forEach( async bill => {
const documents = await BillDocument.find({
where: { id: bill.id },
select: ['content']
});

const billXml = exportBillXml(bill.title, documents);
billsXml.push( billXml );

try {
// First, validate XML.
await postBillForValidation( billXml );

// Second, publish the XML.
await postBillForPublishing( billXml );
} catch( error: any ) {
throw new HttpError( 400, <string>error?.message );
}
} );

return billsXml;
}

@Put('/bills/:id')
@ResponseSchema(Bill)
update(
Expand All @@ -49,4 +89,4 @@ class BillController {
}
}

export default BillController;
export default BillController;
2 changes: 1 addition & 1 deletion server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ void (async () => {
console.log('Generating Client SDK...');
exec('npm run build:sdk');
}
})();
})();
32 changes: 28 additions & 4 deletions server/src/integration/lagasafnApi/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
import axios from 'axios';
import axios, { AxiosRequestConfig } from 'axios';
import { lagasafnApi } from '../../config/lagasafnApi';

const config: AxiosRequestConfig = {
headers: {
'Content-Type': 'application/xml',
},
};

export const postBillForValidation = async (billXml: string) => {
try {
await axios.post(lagasafnApi.url, billXml);
} catch (error) {
await axios.post(
lagasafnApi.url + '/api/bill/document/validate',
billXml,
config
);
} catch (error: any) {
// Do not interrupt processing in case of external service failure
console.log('Request to lagasafn failed', error);
}
};

export const postBillForPublishing = async (billXml: string) => {
try {
await axios.post(
lagasafnApi.url + '/api/bill/document/publish',
billXml,
config
);
} catch (error: any) {
// Do not interrupt processing in case of external service failure
console.log('Request to lagasafn failed', error);
}
};
};
6 changes: 2 additions & 4 deletions server/src/services/DocumentService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ describe('DocumentService', () => {
const identifier = '2023.65';
xmlContent = '<xml></xml>';

const [doc1, doc2] = await Promise.all([
findOrImportDocument(identifier),
findOrImportDocument(identifier),
]);
const doc1 = await findOrImportDocument(identifier);
const doc2 = await findOrImportDocument(identifier);

expect(doc1).toEqual(doc2);
});
Expand Down
Loading