Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-sumner committed Aug 30, 2024
2 parents 1c5bdb8 + 4a8caf5 commit f7609a8
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 94 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ All notable changes to this project will be documented in this file, per [the Ke
### Security
-->

<!-- ... -->
## [1.7.0] - 2024-08-30

### Changed
* Refactored Screenshot HUD to appear in the screenshot by @michael-sumner in #38

<!-- ... -->
## [1.6.0] - 2024-08-19

Expand Down Expand Up @@ -99,6 +105,7 @@ All notable changes to this project will be documented in this file, per [the Ke
- Initial plugin release

[Unreleased]: https://github.com/scoredetect/timestamps/compare/trunk...develop
[1.7.0]: https://github.com/scoredetect/timestamps/compare/1.6.0...1.7.0
[1.6.0]: https://github.com/scoredetect/timestamps/compare/1.5.0...1.6.0
[1.5.0]: https://github.com/scoredetect/timestamps/compare/1.4.1...1.5.0
[1.4.1]: https://github.com/scoredetect/timestamps/compare/1.4.0...1.4.1
Expand Down
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ The `develop` branch is the development branch which means it contains the next

## Release instructions

Open a [new blank issue](https://github.com/scoredetect/timestamps/issues/new) with `[Release] 1.5.0`, then copy and paste the following items, replacing version numbers and links to the milestone.
Open a [new blank issue](https://github.com/scoredetect/timestamps/issues/new) with `[Release] 1.7.0`, then copy and paste the following items, replacing version numbers and links to the milestone.

- [ ] 1. Branch: Starting from `develop`, cut a release branch named `release/1.5.0` for your changes.
- [ ] 1. Branch: Starting from `develop`, cut a release branch named `release/1.7.0` for your changes.
- [ ] 2. Version bump: Bump the version number in `timestamps.php`, `package.json`, `package-lock.json`, `readme.txt`, and any other relevant files if it does not already reflect the version being released. In `timestamps.php` update both the plugin "Version:" property and the plugin `SDCOM_TIMESTAMPS_VERSION` constant.
- [ ] 3. Changelog: Add/update the changelog in `CHANGELOG.md`, ensuring to link the [1.5.0] release reference in the footer of `CHANGELOG.md` (e.g., https://github.com/scoredetect/timestamps/compare/1.5.0-1...1.5.0).
- [ ] 3. Changelog: Add/update the changelog in `CHANGELOG.md`, ensuring to link the [1.7.0] release reference in the footer of `CHANGELOG.md` (e.g., https://github.com/scoredetect/timestamps/compare/1.7.0-1...1.7.0).
- [ ] 4. Props: Update `CREDITS.md` file with any new contributors, confirm maintainers are accurate.
- [ ] 5. Readme updates: Make any other readme changes as necessary. `README.md` is geared toward GitHub and `readme.txt` contains WordPress.org-specific content. The two are slightly different.
- [ ] 6. New files: Check to be sure any new files/paths that are unnecessary in the production version are included in `.distignore`.
Expand All @@ -42,7 +42,7 @@ Open a [new blank issue](https://github.com/scoredetect/timestamps/issues/new) w
- [ ] 12. [Check the _Build and Tag_ action](https://github.com/scoredetect/timestamps/actions/workflows/build-and-tag.yml): a new tag named with the version number should've been created. It should contain all the built assets.
- [ ] 13. Release: Create a [new release](https://github.com/scoredetect/timestamps/releases/new):
* **Tag**: The tag created in the previous step
* **Release title**: `Version 1.5.0`
* **Release title**: `Version 1.7.0`
* **Description**: Release changelog from `CHANGELOG.md` + `See: https://github.com/scoredetect/timestamps/milestone/#?closed=1`
- [ ] 14. SVN: Wait for the [GitHub Action](https://github.com/scoredetect/timestamps/actions/workflows/push-deploy.yml) to finish deploying to the WordPress.org repository. If all goes well, users with SVN commit access for that plugin will receive an emailed diff of changes.
- [ ] 15. Check WordPress.org: Ensure that the changes are live on https://wordpress.org/plugins/timestamps/. This may take a few minutes.
Expand All @@ -51,9 +51,9 @@ Open a [new blank issue](https://github.com/scoredetect/timestamps/issues/new) w

There may be cases where we have an urgent/important fix that ideally gets into a release quickly without any other changes (e.g., a "hotfix") so as to reduce (1) the amount or testing before being confident in the release and (2) to reduce the chance of unintended side effects from the extraneous non-urgent/important changes. In cases where code has previously been merged into `develop` but that ideally is not part of a hotfix, the normal release instructions above will not suffice as they would release all code merged to `develop` alongside the intended urgent/important "hotfix" change(s). In case of needing to release a "hotfix" the following are the recommended steps to take.

1. Branch: Starting from `main`, cut a hotfix release branch named `hotfix/1.5.0` for your hotfix change(s).
1. Branch: Starting from `main`, cut a hotfix release branch named `hotfix/1.7.0` for your hotfix change(s).
1. Version bump: Bump the version number in `timestamps.php`, `package.json`, `readme.txt`, and any other relevant files if it does not already reflect the version being released. In `timestamps.php` update both the plugin "Version:" property and the plugin `SDCOM_TIMESTAMPS_VERSION` constant.
1. Changelog: Add/update the changelog in `CHANGELOG.md` and `readme.txt`, ensuring to link the [1.5.0] release reference in the footer of `CHANGELOG.md` (e.g., https://github.com/scoredetect/timestamps/compare/1.5.0-1...1.5.0).
1. Changelog: Add/update the changelog in `CHANGELOG.md` and `readme.txt`, ensuring to link the [1.7.0] release reference in the footer of `CHANGELOG.md` (e.g., https://github.com/scoredetect/timestamps/compare/1.7.0-1...1.7.0).
1. Props: Update `CREDITS.md` file with any new contributors, confirm maintainers are accurate.
1. Readme updates: Make any other readme changes as necessary. `README.md` is geared toward GitHub and `readme.txt` contains WordPress.org-specific content. The two are slightly different.
1. New files: Check to be sure any new files/paths that are unnecessary in the production version are included in `.distignore`.
Expand Down
251 changes: 178 additions & 73 deletions assets/js/timestamps-screenshot-shortcode/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,129 @@ import QRCode from 'easyqrcodejs'; // eslint-disable-line import/no-extraneous-d
import { PUBLIC_SCOREDETECT_URL } from '../lib/constants';

/**
* Handles the click event on the element.
* Displays a HUD with the certificate ID and a QR code.
*
* This function will take a screenshot of the webpage and create a PDF certificate.
* @param {string} certificateId - The certificate ID.
*
* @param {HTMLButtonElement} btn - The button element.
* @returns {void}
*/
function onClick(btn) {
const { body } = document;
function displayHud({ certificateId = '' }) {
// Create a canvas element.
const canvas = document.createElement('canvas');
canvas.id = 'sdcom_timestamps_hud';
canvas.width = 300;
canvas.height = 300;
canvas.style.position = 'absolute';
canvas.style.top = '0';
canvas.style.right = '0';
canvas.style.zIndex = '999999999'; // Force to be on top.
canvas.style.backgroundColor = 'white';
canvas.style.border = '2px solid black';
canvas.style.padding = '10px';
canvas.style.fontFamily = 'Arial';
canvas.style.fontSize = '12px';

// Get the canvas context.
const ctx = canvas.getContext('2d');

const maxWidth = canvas.width - 20; // Set a maximum width for the text.
const lineHeight = 12; // Set the line height.

// Create QR Code HTML image element.
const qrCodeSize = 200;
const qrCodeId = 'qrcode';

const qrCodeElement = new Image();
qrCodeElement.width = qrCodeSize;
qrCodeElement.height = qrCodeSize;
qrCodeElement.id = qrCodeId;

document.body.appendChild(qrCodeElement);

document.getElementById(qrCodeId).style.display = 'none';

const publicLedgerUrl = `${PUBLIC_SCOREDETECT_URL}/certificate/${certificateId}`;

// Create QR Code Object.
const qrcode = new QRCode(document.getElementById(qrCodeId), {
text: publicLedgerUrl,
});

// Get QR Code Data URL.
const qrCodeDataUrl = qrcode._el.childNodes[0].toDataURL('image/png');

qrCodeElement.src = qrCodeDataUrl;

// Draw the QR code on the canvas.
qrCodeElement.onload = () => {
ctx.drawImage(qrCodeElement, 50, 55, canvas.width - 100, canvas.height - 100);
};

// Remove the QR Code element from the DOM.
document.body.removeChild(qrCodeElement);

// Wrap the text. Defaults to every 50 characters.
function wrapText(context, text, x, y, maxWidth, lineHeight, maxChars = 50) {
const lines = [];
for (let i = 0; i < text.length; i += maxChars) {
lines.push(text.substring(i, i + maxChars));
}

for (let k = 0; k < lines.length; k++) {
context.fillText(lines[k], x, y + k * lineHeight);
}
}

ctx.fillStyle = 'black';
ctx.textAlign = 'center';
ctx.font = '20px Arial';

wrapText(
ctx,
__('Blockchain Safety', 'timestamps'),
canvas.width / 2,
45,
maxWidth,
lineHeight,
30,
);

ctx.font = '12px Arial';

// Display the date and time to the bottom but inside the square.
const now = new Date();
const dateTimeString = `${now.toUTCString()} UTC+0`;
wrapText(ctx, dateTimeString, canvas.width / 2, canvas.height - 25, maxWidth, lineHeight, 40);

// Display the certificate ID to the bottom but inside the square.
wrapText(ctx, certificateId, canvas.width / 2, canvas.height - 10, maxWidth, lineHeight, 40);

// Display the canvas element.
document.body.appendChild(canvas);
}

/**
* Removes the HUD from the DOM.
*
* @returns {void}
*/
function removeHud() {
const hud = document.getElementById('sdcom_timestamps_hud');
if (hud) {
hud.remove();
}
}

/**
* Handles the screenshot and creates a PDF certificate.
*
* @param {HTMLElement} body - The body element.
* @param {HTMLButtonElement} btn - The button element.
* @param {string} certificateId - The certificate ID.
*
* @returns {void}
*/
function handleScreenshot({ body, btn, certificateId }) {
// Get the original button text.
const originalText = btn.innerHTML;

Expand Down Expand Up @@ -74,6 +188,10 @@ function onClick(btn) {
formData.append('file', file);
formData.append('action', 'sdcom_timestamps_screenshot');

if (certificateId) {
formData.append('id', certificateId);
}

const a = document.createElement('a');
const img = URL.createObjectURL(blob);
a.href = img;
Expand All @@ -90,6 +208,9 @@ function onClick(btn) {
// Remove the canvas element.
canvas.remove();

// Remove the HUD.
removeHud();

// Restore the WP admin bar.
if (adminBar) {
adminBar.style.display = 'block';
Expand Down Expand Up @@ -278,73 +399,6 @@ function onClick(btn) {
doc.setDrawColor(0, 0, 0);
doc.rect(0, 0, newWidth, newHeight).stroke();

// Create QR Code HTML image element.
const qrCodeSize = 30;
const qrCodeElement = document.createElement('div');
const qrCodeId = 'qrcode';
qrCodeElement.id = qrCodeId;
document.body.appendChild(qrCodeElement);
document.getElementById(qrCodeId).style.display = 'none';

// Add a text above the QR code.
doc.setFontSize(8);
doc.setFont(undefined, 'bold');
doc.text(
__('Blockchain Safety', 'timestamps'),
pageWidth - qrCodeSize - 10,
10,
);

// Create QR Code Object.
const qrcode = new QRCode(document.getElementById(qrCodeId), {
text: publicLedgerUrl,
});

// Get QR Code Data URL.
const qrCodeDataUrl = qrcode._el.childNodes[0].toDataURL('image/png');

// Remove the QR Code element from the DOM.
document.body.removeChild(qrCodeElement);

// Add the QR code to the PDF.
doc.addImage(
qrCodeDataUrl,
'PNG',
pageWidth - qrCodeSize - 10,
10 + 2,
qrCodeSize,
qrCodeSize,
);

// Add the `certificate checksum` under the QR code.
doc.setFont(undefined, 'normal');
doc.setFontSize(5);
doc.text(
`sha256:${certificate.blockchain_transaction_checksum}`,
pageWidth - 10 - 1, // hard-coded x-coordinate to place it under the QR code.
qrCodeSize + 15, // hard-coded y-coordinate to place it under the QR code.
{
angle: -90,
},
);

// Add the `certificate created_at` under the QR code.
doc.text(
sprintf(
/* translators: %s: Created at date */
__('Created at: %s UTC+0', 'timestamps'),
certificate.created_at,
),
pageWidth - 10 - 1 - 2, // hard-coded x-coordinate to place it under the QR code.
qrCodeSize + 15, // hard-coded y-coordinate to place it under the QR code.
{
angle: -90,
},
);

// Reset the font size.
doc.setFontSize(10);

const totalPagesExp = doc.internal.getNumberOfPages();

const setFooter = () => {
Expand Down Expand Up @@ -382,7 +436,10 @@ function onClick(btn) {
const centerY = pageHeight / 2 + 10;

// Set the text alignment to center.
doc.text(watermarkText, centerX, centerY, { align: 'center', angle: 30 });
doc.text(watermarkText, centerX, centerY, {
align: 'center',
angle: 30,
});

// Setup PDF footer.
autoTable(doc, {
Expand Down Expand Up @@ -420,6 +477,54 @@ function onClick(btn) {
});
}

/**
* Handles the click event on the element.
*
* This function will take a screenshot of the webpage and create a PDF certificate.
*
* @param {HTMLButtonElement} btn - The button element.
*/
function onClick(btn) {
const formDataCertificateId = new FormData();
formDataCertificateId.append(
'nonce',
sdcom_timestamps_screenshot.generate_certificate_id_nonce,
);
formDataCertificateId.append('action', 'sdcom_timestamps_screenshot_generate_certificate_id');

try {
fetch(sdcom_timestamps_screenshot.ajaxurl, {
method: 'POST',
body: formDataCertificateId,
})
.then((response) => response.json())
.then((data) => {
if (!data.success) {
throw new Error(data.data.message);
}

const { uuid } = data.data;

const certificateId = uuid;

// Display the HUD.
displayHud({
certificateId,
});

// Wait a bit for the HUD to be displayed before taking the screenshot.
setTimeout(() => {
handleScreenshot({ body: document.body, btn, certificateId: uuid });
}, 1);
})
.catch((error) => {
console.error(error);
});
} catch (error) {
console.error(error);
}
}

/**
* Initializes the script.
*
Expand Down
Loading

0 comments on commit f7609a8

Please sign in to comment.