fix: Fix Material web pre15 BC

This commit is contained in:
Maicol Battistini 2023-08-17 15:36:30 +02:00
parent 446011eecb
commit 13a6dba0ed
No known key found for this signature in database
16 changed files with 132 additions and 100 deletions

View File

@ -174,7 +174,7 @@
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="27">
<list size="30">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
@ -202,6 +202,9 @@
<item index="24" class="java.lang.String" itemvalue="md-menu" />
<item index="25" class="java.lang.String" itemvalue="md-outlined-select" />
<item index="26" class="java.lang.String" itemvalue="md-filled-select" />
<item index="27" class="java.lang.String" itemvalue="md-data-table" />
<item index="28" class="java.lang.String" itemvalue="md-filled-icon-button" />
<item index="29" class="java.lang.String" itemvalue="md-dialog" />
</list>
</value>
</option>

View File

@ -8,10 +8,9 @@ md-icon svg {
line-height: 0;
}
:is(md-list-item, md-list-item-link) md-icon {
--md-icon-color: var(--_list-item-leading-icon-color);
padding-left: 16px;
md-list-item md-icon {
margin-left: 16px;
color: var(--_list-item-leading-icon-color);
svg {
width: var(--_list-item-leading-icon-size, var(--_icon-size, var(--_size)));
@ -42,7 +41,7 @@ md-navigation-drawer, md-navigation-drawer-modal {
justify-content: center;
min-width: 300px;
md-list-item-link {
md-list-item {
--md-list-item-list-item-container-shape: 100px;
--md-ripple-shape: 100px;

View File

@ -1,6 +1,6 @@
import '@maicol07/material-web-additions/data-table/data-table.js';
import {DataTable as MdDataTable} from '@maicol07/material-web-additions/data-table/lib/data-table';
import {DataTable as MdDataTable} from '@maicol07/material-web-additions/data-table/internal/data-table';
import {
mdiChevronLeft,
mdiChevronRight,

View File

@ -1,6 +1,6 @@
import '@maicol07/material-web-additions/data-table/data-table-column.js';
import {DataTableColumn as MdDataTableColumn} from '@maicol07/material-web-additions/data-table/lib/data-table-column.js';
import {DataTableColumn as MdDataTableColumn} from '@maicol07/material-web-additions/data-table/internal/data-table-column.js';
import {
mdiArrowDown,
mdiArrowUp

View File

@ -7,8 +7,8 @@ import {
DataTable as MdDataTable,
PaginateDetail,
RowSelectionChangedDetail
} from '@maicol07/material-web-additions/data-table/lib/data-table';
import {DataTableCell} from '@maicol07/material-web-additions/data-table/lib/data-table-cell';
} from '@maicol07/material-web-additions/data-table/internal/data-table';
import {DataTableCell} from '@maicol07/material-web-additions/data-table/internal/data-table-cell';
import {mdiDeleteOutline} from '@mdi/js';
import DataTable, {DataTableAttributes} from '@osm/Components/DataTable/DataTable';
import DataTableColumn, {DataTableColumnAttributes} from '@osm/Components/DataTable/DataTableColumn';
@ -171,9 +171,9 @@ export default class RecordsTable<M extends Model<any, any>, A extends RecordsTa
protected tableRowActions(vnode: Vnode<A>, record: M) {
return collect<Children>({
delete: (
<md-standard-icon-button onclick={this.onDeleteRecordButtonClicked.bind(this, vnode, record)}>
<md-icon-button onclick={this.onDeleteRecordButtonClicked.bind(this, vnode, record)}>
<MdIcon icon={mdiDeleteOutline}/>
</md-standard-icon-button>
</md-icon-button>
)
});
}

View File

@ -31,6 +31,7 @@ export default abstract class AddEditRecordDialog<M extends Model<any, any>> ext
// Recommended: <= 3
protected numberOfColumns: number = 3;
protected record!: M;
protected formId?: string;
oninit(vnode: Vnode<RecordDialogAttributes<M>, this>) {
super.oninit(vnode);
@ -57,16 +58,19 @@ export default abstract class AddEditRecordDialog<M extends Model<any, any>> ext
contents(): Children {
return (
<>
<h2 slot="headline">{this.record.isNew() ? __('Nuovo record') : __('Modifica record')}</h2>
{this.form()}
{this.afterForm().toArray()}
</>
);
}
headline() {
return <span slot="headline">{this.record.isNew() ? __('Nuovo record') : __('Modifica record')}</span>;
}
form(): Children {
this.formId ??= `form-${Date.now()}`;
return (
<Form state={this.formState} onsubmit={this.onFormSubmit.bind(this)}>
<Form id={this.formId} state={this.formState} onsubmit={this.onFormSubmit.bind(this)}>
{this.formContents()}
</Form>
);
@ -95,24 +99,24 @@ export default abstract class AddEditRecordDialog<M extends Model<any, any>> ext
abstract fields(): Collection<Children>;
onCancelButtonClicked(): void {
this.close('cancel');
void this.close('cancel');
}
async onFormSubmit() {
if (isFormValid(this.formElement!) && await this.save()) {
this.close();
void this.close();
}
}
afterForm(): VnodeCollection {
actions(): VnodeCollection {
return collect<VnodeCollectionItem>({
cancelButton: (
<md-text-button slot="footer" onclick={this.onCancelButtonClicked.bind(this)}>
<md-text-button onclick={this.onCancelButtonClicked.bind(this)}>
{__('Annulla')}
</md-text-button>
),
saveButton: (
<md-text-button type="submit" slot="footer" onclick={this.onSaveButtonClicked.bind(this)}>
<md-text-button type="submit" form={this.formId}>
{__('Salva')}
<MdIcon icon={mdiFloppy} slot="icon"/>
</md-text-button>
@ -120,10 +124,6 @@ export default abstract class AddEditRecordDialog<M extends Model<any, any>> ext
});
}
onSaveButtonClicked(): void {
this.formElement?.requestSubmit();
}
async save(): Promise<boolean> {
this.record.setAttributes(this.modelAttributesFromFormState);
try {
@ -136,9 +136,7 @@ export default abstract class AddEditRecordDialog<M extends Model<any, any>> ext
}
}
// @ts-expect-error - Temporary
afterSave(response: SaveResponse<M>): void {
// @ts-expect-error - Temporary
const responseModel = response.getModel() as M;
if (responseModel !== undefined) {
this.record = responseModel;

View File

@ -4,9 +4,13 @@ import '@material/web/dialog/dialog.js';
import {Dialog as MDDialog} from '@material/web/dialog/internal/dialog';
import {
VnodeCollection,
VnodeCollectionItem
} from '@osm/typings/jsx';
import collect from 'collect.js';
import Mithril, {
Children,
Vnode,
VnodeDOM
Vnode
} from 'mithril';
import Stream from 'mithril/stream';
import {
@ -36,40 +40,63 @@ export default abstract class Dialog<A extends DialogAttributes = DialogAttribut
this.open = open;
}
oncreate(vnode: VnodeDOM<A, this>) {
super.oncreate(vnode);
this.element.addEventListener('closed', () => {
vnode.attrs.onClose?.();
this.open(false);
m.redraw();
});
this.element.addEventListener('opened', () => {
vnode.attrs.onOpen?.();
});
}
public view(vnode: Vnode<A, this>): Children {
let open = this.open();
// If dialog is open but element isn't created yet, don't open it (wait for oncreate, see below)
if (open && this.element === undefined) {
open = false;
}
const contents = this.contents(vnode) ?? vnode.children;
const actions = this.actions(vnode);
return (
<md-dialog style={{
'--md-dialog-container-max-block-size': 'calc(100% - 48px)',
'--md-dialog-container-max-inline-size': 'calc(100% - 48px)'
}} {...vnode.attrs} open={this.open()}>
{this.contents(vnode) ?? vnode.children}
maxWidth: 'calc(100% - 48px)',
maxHeight: 'calc(100% - 48px)'
}} {...vnode.attrs} open={open} onopened={vnode.attrs.onOpen} onclosed={this.onDialogClosed.bind(this, vnode)}>
{this.icon() && <div slot="icon">{this.icon()}</div>}
{this.headline() && <div slot="headline">{this.headline()}</div>}
{contents && <div slot="content">{contents}</div>}
{actions.isNotEmpty() && <div slot="actions">{actions.toArray()}</div>}
</md-dialog>
);
}
oncreate(vnode: Mithril.VnodeDOM<A, this>) {
super.oncreate(vnode);
// TODO: [BUG] Dialog not opening by default on creation. Wait for https://github.com/material-components/material-web/issues/4728
setTimeout(() => {
if (this.open()) {
void this.show();
}
}, 0);
}
onDialogClosed(vnode:Vnode<A, this>) {
vnode.attrs.onClose?.();
this.open(false);
}
icon(): Children {
return undefined;
}
headline(): Children {
return undefined;
}
contents(vnode: Vnode<A, this>): Children {
return undefined;
}
public show(): void {
this.element.show();
actions(vnode: Vnode<A, this>): VnodeCollection {
return collect<VnodeCollectionItem>();
}
public close(action?: string): void {
this.element.close(action);
public async show() {
return this.element.show();
}
public async close(action?: string) {
return this.element.close(action);
}
}

View File

@ -1,5 +1,5 @@
import '@material/web/textfield/filled-text-field.js';
import '@material/web/iconbutton/standard-icon-button.js';
import '@material/web/iconbutton/icon-button.js';
import {FilledTextField} from '@material/web/textfield/internal/filled-text-field';
import {mdiCalendarMonthOutline} from '@mdi/js';
@ -21,9 +21,9 @@ export default class FilledDateTextField<A extends FilledDateTextFieldAttributes
<md-filled-text-field {...vnode.attrs}>
{/* @ts-ignore */}
{vnode.children}
<md-standard-icon-button slot="trailingicon" onclick={this.openDatePicker.bind(this)}>
<md-icon-button slot="trailingicon" onclick={this.openDatePicker.bind(this)}>
<MdIcon icon={mdiCalendarMonthOutline}/>
</md-standard-icon-button>
</md-icon-button>
</md-filled-text-field>
);
}

View File

@ -3,14 +3,14 @@ import '@maicol07/material-web-additions/layout-grid/layout-grid.js';
import '@material/web/dialog/dialog.js';
import '@material/web/fab/branded-fab.js';
import '@material/web/fab/fab.js';
import '@material/web/iconbutton/standard-icon-button.js';
import '@material/web/iconbutton/icon-button.js';
import {router} from '@maicol07/inertia-mithril';
import {PaginateDetail} from '@maicol07/material-web-additions/data-table/lib/data-table';
import {PaginateDetail} from '@maicol07/material-web-additions/data-table/internal/data-table';
import {
FilterTextFieldInputEventDetail,
SortButtonClickedEventDetail
} from '@maicol07/material-web-additions/data-table/lib/data-table-column.js';
} from '@maicol07/material-web-additions/data-table/internal/data-table-column.js';
import {
mdiPlus,
mdiRefresh

View File

@ -40,7 +40,7 @@ export default class Drawer<A extends DrawerAttributes = DrawerAttributes> exten
const DrawerTag = isMobile() ? 'md-navigation-drawer-modal' : 'md-navigation-drawer';
return (
<DrawerTag opened={this.open()}>
{DrawerTag === 'md-navigation-drawer-modal' && <md-standard-icon-button onclick={this.onMobileMenuButtonClick.bind(this)}><MdIcon icon={mdiMenuOpen}/></md-standard-icon-button>}
{DrawerTag === 'md-navigation-drawer-modal' && <md-icon-button onclick={this.onMobileMenuButtonClick.bind(this)}><MdIcon icon={mdiMenuOpen}/></md-icon-button>}
<md-list>{this.entries().values<VnodeCollectionItem>().all()}</md-list>
</DrawerTag>
);

View File

@ -1,8 +1,8 @@
import '@material/web/icon/icon.js';
import '@material/web/list/list-item-link.js';
import '@material/web/list/list-item.js';
import {router} from '@maicol07/inertia-mithril';
import {ListItemLink} from '@material/web/list/internal/listitemlink/list-item-link';
import {ListItemEl} from '@material/web/list/internal/listitem/list-item';
import type * as MaterialIcons from '@mdi/js';
import MdIcon from '@osm/Components/MdIcon';
import {Vnode} from 'mithril';
@ -14,17 +14,17 @@ import {ValueOf} from 'type-fest';
type Icons = ValueOf<typeof MaterialIcons>;
export interface DrawerEntryAttributes extends Attributes, Partial<ListItemLink> {
href: ListItemLink['href'];
export interface DrawerEntryAttributes extends Attributes, Partial<ListItemEl> {
href: ListItemEl['href'];
icon: Icons;
}
export class DrawerEntry<A extends DrawerEntryAttributes = DrawerEntryAttributes> extends Component<A> {
view(vnode: Vnode<A>) {
return (
<md-list-item-link headline={vnode.children as string} active={this.isRouteActive(vnode.attrs.href)} href={vnode.attrs.href} onclick={this.navigateToRoute.bind(this)} {...this.attrs.all()}>
<md-list-item headline={vnode.children as string} active={this.isRouteActive(vnode.attrs.href)} href={vnode.attrs.href} onclick={this.navigateToRoute.bind(this)} {...this.attrs.all()}>
<MdIcon icon={vnode.attrs.icon} slot="start"/>
</md-list-item-link>
</md-list-item>
);
}
@ -34,6 +34,6 @@ export class DrawerEntry<A extends DrawerEntryAttributes = DrawerEntryAttributes
navigateToRoute(event: Event) {
event.preventDefault();
router.visit((event.target as ListItemLink).href);
router.visit((event.target as ListItemEl).href);
}
}

View File

@ -1,4 +1,4 @@
import '@material/web/iconbutton/standard-icon-button.js';
import '@material/web/iconbutton/icon-button.js';
import '@osm/WebComponents/TopAppBar';
import {
@ -54,9 +54,9 @@ export default class TopAppBar extends Component {
navigationIcon(vnode: Vnode) {
return (
<md-standard-icon-button slot="navigationIcon" onclick={this.onNavigationIconClick.bind(this)}>
<md-icon-button slot="navigationIcon" onclick={this.onNavigationIconClick.bind(this)}>
<MdIcon icon={this.drawerOpenState() ? mdiMenuOpen : mdiMenu}/>
</md-standard-icon-button>
</md-icon-button>
);
}

View File

@ -12,9 +12,9 @@ export default abstract class TopAppBarAction extends Component {
view(vnode: Vnode): Children {
return (
<md-standard-icon-button id={this.id} slot="actionItems" ariaLabel={this.ariaLabel} onclick={this.callback.bind(this)}>
<md-icon-button id={this.id} slot="actionItems" ariaLabel={this.ariaLabel} onclick={this.callback.bind(this)}>
<MdIcon icon={this.icon}/>
</md-standard-icon-button>
</md-icon-button>
);
}

View File

@ -5,7 +5,6 @@ import '@material/web/checkbox/checkbox.js';
import '@material/web/dialog/dialog.js';
import '@material/web/textfield/filled-text-field.js';
import {Dialog} from '@material/web/dialog/internal/dialog';
import {
mdiAccountOutline,
mdiEmailOutline,
@ -19,8 +18,7 @@ import {VnodeCollectionItem} from '@osm/typings/jsx';
import {showSnackbar} from '@osm/utils/misc';
import collect from 'collect.js';
import type {
Vnode,
VnodeDOM
Vnode
} from 'mithril';
import Stream from 'mithril/stream';
import {
@ -41,7 +39,7 @@ export default class LoginPage extends Page {
email: Stream('')
};
forgotPasswordDialog!: Dialog;
forgotPasswordDialogOpen = false;
contents(vnode: Vnode<PageAttributes>) {
return <>
@ -52,18 +50,25 @@ export default class LoginPage extends Page {
{this.buttons().toArray()}
</div>
</Form>
<md-dialog id="forgot-password-dialog">
<h2 slot="headline">{__('Recupero password')}</h2>
<p>{__('Inserisci il tuo indirizzo email per ricevere le istruzioni per il recupero della password.')}</p>
<Form id="forgot-password" onsubmit={this.onForgotPasswordFormSubmit.bind(this)} state={this.forgotPasswordForm}>
<div style={{textAlign: 'center'}}>
{this.forgotPasswordFields().toArray()}
</div>
</Form>
<md-text-button dialog-action="cancel" slot="footer" label={__('Annulla')}></md-text-button>
<md-filled-button slot="footer" onclick={this.onForgotPasswordDialogSubmitButtonClicked.bind(this)}>
{__('Invia')}
</md-filled-button>
<md-dialog id="forgot-password-dialog" open={this.forgotPasswordDialogOpen} onclosed={this.closeForgotPasswordDialog.bind(this)}>
<div slot="icon">
<MdIcon icon={mdiLockQuestion}/>
</div>
<div slot="headline">
<span>{__('Recupero password')}</span>
</div>
<div slot="content">
<p>{__('Inserisci il tuo indirizzo email per ricevere le istruzioni per il recupero della password.')}</p>
<Form id="forgot-password" onsubmit={this.onForgotPasswordFormSubmit.bind(this)} state={this.forgotPasswordForm}>
<div style={{textAlign: 'center'}}>
{this.forgotPasswordFields().toArray()}
</div>
</Form>
</div>
<div slot="actions">
<md-text-button onclick={this.onForgotPasswordDialogCancelButtonClicked.bind(this)}>{__('Annulla')}</md-text-button>
<md-text-button form="forgot-password">{__('Invia')}</md-text-button>
</div>
</md-dialog>
</>;
}
@ -82,7 +87,7 @@ export default class LoginPage extends Page {
),
remember: (
<label>
<md-checkbox name="remember"/>
<md-checkbox name="remember" touch-target="wrapper"/>
<span>{__('Ricordami')}</span>
</label>
)
@ -102,7 +107,7 @@ export default class LoginPage extends Page {
buttons() {
return collect<VnodeCollectionItem>({
forgotPassword: (
<md-text-button id="forgot-password-button" onclick={this.onForgotPasswordButtonClicked.bind(this)}>
<md-text-button type="button" id="forgot-password-button" onclick={this.onForgotPasswordButtonClicked.bind(this)}>
{__('Password dimenticata')}
<MdIcon icon={mdiLockQuestion} slot="icon"/>
</md-text-button>
@ -116,12 +121,6 @@ export default class LoginPage extends Page {
});
}
oncreate(vnode: VnodeDOM<PageAttributes, this>) {
super.oncreate(vnode);
this.forgotPasswordDialog = this.element.querySelector<Dialog>('md-dialog#forgot-password-dialog')!;
}
async onLoginFormSubmit(event: FormSubmitEvent) {
try {
await Request.get(route('sanctum.csrf-cookie'));
@ -136,11 +135,19 @@ export default class LoginPage extends Page {
}
onForgotPasswordButtonClicked() {
this.forgotPasswordDialog.show();
this.openForgotPasswordDialog();
}
onForgotPasswordDialogSubmitButtonClicked() {
this.forgotPasswordDialog.querySelector('form')?.requestSubmit();
onForgotPasswordDialogCancelButtonClicked() {
this.closeForgotPasswordDialog();
}
openForgotPasswordDialog() {
this.forgotPasswordDialogOpen = true;
}
closeForgotPasswordDialog() {
this.forgotPasswordDialogOpen = false;
}
async onForgotPasswordFormSubmit(event: FormSubmitEvent) {
@ -152,6 +159,6 @@ export default class LoginPage extends Page {
}
void showSnackbar(__('La password è stata inviata alla tua email'));
this.forgotPasswordDialog.close();
this.closeForgotPasswordDialog();
}
}

View File

@ -12,7 +12,7 @@ declare global {
export default class TopAppBar extends MWCTopAppBar {
static styles = [...MWCTopAppBar.styles, css`
header.mdc-top-app-bar {
z-index: 7;
z-index: 0;
}
`];
}

View File

@ -19,8 +19,6 @@ declare module 'csstype' {
declare module 'mithril' {
interface Attributes extends LayoutGridAttributes {
// Needed for md-dialog
'dialog-action'?: string | 'ok' | 'discard' | 'close' | 'cancel' | 'accept' | 'decline',
'auto-animate'?: boolean
}
}