Add logo preview to creator settings form (#15363)
This commit is contained in:
parent
ef83f0b07b
commit
ca0db28fc4
9 changed files with 121 additions and 14 deletions
|
|
@ -18,6 +18,11 @@ body.default-header {
|
|||
background: white;
|
||||
}
|
||||
|
||||
[data-creator-settings-target='previewLogo'] {
|
||||
max-height: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
// This ID is tied the global "Setup not complete" banner
|
||||
// and is necessary for the removal of the banner on the
|
||||
// Creator Settings page
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ module.exports = {
|
|||
'@crayons': path.join(__dirname, './crayons'),
|
||||
'@utilities': path.join(__dirname, './utilities'),
|
||||
'@components': path.join(__dirname, './shared/components'),
|
||||
'@admin-controllers': path.join(__dirname, './admin/controllers'),
|
||||
},
|
||||
extensions: ['.js', '.jsx'],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
const MAX_LOGO_PREVIEW_HEIGHT = 80;
|
||||
const MAX_LOGO_PREVIEW_WIDTH = 220;
|
||||
|
||||
/**
|
||||
* Manages interactions on the Creator Settings page.
|
||||
*/
|
||||
export class CreatorSettingsController extends Controller {
|
||||
static targets = ['previewLogo'];
|
||||
|
||||
/**
|
||||
* Displays a preview of the image selected by the user.
|
||||
*
|
||||
* @param {Event} event
|
||||
*/
|
||||
previewLogo(event) {
|
||||
const {
|
||||
target: {
|
||||
files: [firstFile],
|
||||
},
|
||||
} = event;
|
||||
|
||||
if (!firstFile) {
|
||||
// Most likely the user cancelled the file selection.
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = () => {
|
||||
const imageURL = reader.result;
|
||||
const image = document.createElement('img');
|
||||
image.src = imageURL;
|
||||
|
||||
// The logo preview image is purely visual so no need to communicate this to assistive technology.
|
||||
image.alt = 'preview of logo selected';
|
||||
|
||||
image.addEventListener(
|
||||
'load',
|
||||
(event) => {
|
||||
let {
|
||||
target: { width, height },
|
||||
} = event;
|
||||
|
||||
if (height > MAX_LOGO_PREVIEW_HEIGHT) {
|
||||
width = (width / height) * MAX_LOGO_PREVIEW_HEIGHT;
|
||||
height = MAX_LOGO_PREVIEW_HEIGHT;
|
||||
}
|
||||
|
||||
if (width > MAX_LOGO_PREVIEW_WIDTH) {
|
||||
width = MAX_LOGO_PREVIEW_WIDTH;
|
||||
height = (height / width) * MAX_LOGO_PREVIEW_WIDTH;
|
||||
}
|
||||
|
||||
image.style.width = `${width}px`;
|
||||
image.style.height = `${height}px`;
|
||||
|
||||
this.previewLogoTarget.replaceChild(
|
||||
image,
|
||||
this.previewLogoTarget.firstChild,
|
||||
);
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(firstFile);
|
||||
}
|
||||
}
|
||||
|
|
@ -143,3 +143,23 @@ getInstantClick().then((spa) => {
|
|||
});
|
||||
|
||||
initializeNav();
|
||||
|
||||
async function loadCreatorSettings() {
|
||||
try {
|
||||
const [{ CreatorSettingsController }, { Application }] = await Promise.all([
|
||||
import('@admin-controllers/creator_settings_controller'),
|
||||
import('@hotwired/stimulus'),
|
||||
]);
|
||||
|
||||
const application = Application.start();
|
||||
application.register('creator-settings', CreatorSettingsController);
|
||||
} catch (error) {
|
||||
Honeybadger.notify(
|
||||
`Error loading the creator settings controller: ${error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.location.pathname === '/admin/creator_settings/new') {
|
||||
loadCreatorSettings();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,17 +11,16 @@
|
|||
<%= label_tag :logo_svg, class: "crayons-field__label" do %>
|
||||
Logo
|
||||
<span class="crayons-field__required crayons-tooltip" data-tooltip="This will set the logo for your Forem" aria-describedby="logo-subtitle"></span>
|
||||
<p id="logo-subtitle" class="crayons-field__description">Ideally SVG, but PNG will work, too. Min size: 300x300px.</p>
|
||||
<p id="logo-subtitle" class="crayons-field__description">Ideally SVG, but PNG or JPEG will work, too.</p>
|
||||
<% end %>
|
||||
<span class="block border-none">
|
||||
<%= file_field_tag :logo_svg, class: "crayons-btn crayons-btn--secondary w-100 ", role: "button", required: true %>
|
||||
</span>
|
||||
|
||||
<% if ::Settings::General.logo_svg.present? %>
|
||||
<div class="site-logo">
|
||||
<%= ::Settings::General.logo_svg.html_safe %>
|
||||
<div class="flex flex-1 gap-4">
|
||||
<%= file_field_tag :logo_svg, required: true, accept: ".svg,.png,.jpg,image/svg+xml,image/png,image/jpg", data: { "max-file-size-mb": "25", action: "change->creator-settings#previewLogo" }, aria: { describedby: "logo-subtitle" } %>
|
||||
<div data-creator-settings-target="previewLogo">
|
||||
<% if ::Settings::General.logo_svg.present? %>
|
||||
<%= ::Settings::General.logo_svg.html_safe %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field mt-6 align-left">
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<%= Rails.application.assets["setup-mode.css"].to_s.html_safe %>
|
||||
</style>
|
||||
|
||||
<main id="main-content" class="flex flex-1 justify-center flex-col crayons-layout crayons-layout--limited-xs">
|
||||
<main id="main-content" class="flex flex-1 justify-center flex-col crayons-layout crayons-layout--limited-xs" data-controller="creator-settings">
|
||||
<div aria-live="assertive">
|
||||
<% if flash[:error] %>
|
||||
<div class="crayons-notice crayons-notice--danger mb-6" role="alert">
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ environment.splitChunks((config) => {
|
|||
...(config.resolve ? config.resolve.alias : {}),
|
||||
'@crayons': path.resolve(__dirname, '../../app/javascript/crayons'),
|
||||
'@utilities': path.resolve(__dirname, '../../app/javascript/utilities'),
|
||||
'@admin-controllers': path.resolve(
|
||||
__dirname,
|
||||
'../../app/javascript/admin/controllers',
|
||||
),
|
||||
'@components': path.resolve(
|
||||
__dirname,
|
||||
'../../app/javascript/shared/components',
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@ describe('Creator Settings Page', () => {
|
|||
cy.get('@communityName').type('Climbing Life');
|
||||
|
||||
// should contain a logo upload field and upload a logo upon click
|
||||
cy.findByText(/^Logo/).should('be.visible');
|
||||
cy.findByRole('button', { name: /logo/i }).attachFile(
|
||||
cy.findByLabelText(/logo/i, { selector: 'input' }).attachFile(
|
||||
'/images/admin-image.png',
|
||||
);
|
||||
cy.findByRole('img', { name: /preview of logo selected/i }).should(
|
||||
'be.visible',
|
||||
);
|
||||
|
||||
// should contain a brand color field
|
||||
cy.findByText(/^Brand color/).should('be.visible');
|
||||
|
|
@ -63,7 +65,12 @@ describe('Creator Settings Page', () => {
|
|||
'have.attr',
|
||||
'required',
|
||||
);
|
||||
cy.findByRole('button', { name: /logo/i }).should('have.attr', 'required');
|
||||
|
||||
cy.findByLabelText(/logo/i, { selector: 'input' }).should(
|
||||
'have.attr',
|
||||
'required',
|
||||
);
|
||||
|
||||
// should not redirect the creator to the home page when the form is not completely filled out and 'Finish' is clicked
|
||||
cy.findByRole('button', { name: 'Finish' }).click();
|
||||
cy.url().should('equal', `${baseUrl}admin/creator_settings/new`);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
"paths": {
|
||||
"@crayons/*": ["app/javascript/crayons/*"],
|
||||
"@utilities/*": ["app/javascript/utilities/*"],
|
||||
"@components/*": ["app/javascript/shared/components/*"]
|
||||
"@components/*": ["app/javascript/shared/components/*"],
|
||||
"@admin-controllers/*": ["app/javascript/admin/controllers/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "**/node_modules/*"]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue