Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/bootstrap5'
Browse files Browse the repository at this point in the history
# Conflicts:
#	Signum.Engine.Extensions/Migrations/MigrationLogic.cs
#	Signum.Entities.Extensions/Mailing/ImageAttachmentEntity.cs
#	Signum.React.Extensions/TypeHelp/TypeHelpComponent.tsx
#	Signum.Upgrade/CodeFile.cs
#	Signum.Upgrade/UpgradeContext.cs
  • Loading branch information
olmobrutall committed Nov 12, 2021
2 parents 9e4dce9 + 002bcc9 commit 7d0804c
Show file tree
Hide file tree
Showing 130 changed files with 1,183 additions and 1,018 deletions.
10 changes: 5 additions & 5 deletions Signum.Engine.Extensions/Migrations/MigrationLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public static void Start(SchemaBuilder sb)
if (count > 0)
{
Console.Write("The database ");
SafeConsole.WriteLineColor(ConsoleColor.White, Connector.Current.DatabaseName());
SafeConsole.WriteColor(ConsoleColor.Yellow, Connector.Current.DatabaseName());
Console.Write(" contains ");
SafeConsole.WriteLineColor(ConsoleColor.White, count.ToString());
Console.Write(" Sql Migrations!");
SafeConsole.WriteColor(ConsoleColor.Yellow, count.ToString());
Console.WriteLine(" Sql Migrations!");
if (SafeConsole.Ask("Do you want to create a new SQL Migration instead?"))
{
Expand Down Expand Up @@ -107,7 +107,7 @@ public static void EnsureMigrationTable<T>() where T : Entity
}

SafeConsole.WriteLineColor(ConsoleColor.White, "Table " + table.Name + " auto-generated...");

tr.Commit();
}
}
Expand Down Expand Up @@ -138,7 +138,7 @@ public static void EnsureMigrationTable<T>() where T : Entity
return null;
}
catch (Exception e)
{
{
Console.WriteLine();

SafeConsole.WriteColor(ConsoleColor.Red, e.GetType() + ": ");
Expand Down
4 changes: 2 additions & 2 deletions Signum.Entities.Extensions/Mailing/ImageAttachmentEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public string? FileName

public EmailAttachmentType Type { get; set; }


public FileEmbedded File { get; set; }

[AutoExpressionField]
public override string ToString() => As.Expression(() => FileName ?? File.FileName);
public override string ToString() => As.Expression(() => FileName ?? (File == null ? "" : File.FileName));
}
12 changes: 6 additions & 6 deletions Signum.React.Extensions/Alerts/AlertDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ function AlertDropdownImp(props: { checkForChangesEvery: number, keepRingingFor:
<>
<div className="nav-link sf-bell-container" onClick={handleOnToggle}>
<FontAwesomeIcon icon="bell" className={classes("sf-bell", ringing && "ringing", isOpen && "open", countResult && countResult.numAlerts > 0 && "active")} />
{countResult && countResult.numAlerts > 0 && <span className="badge badge-danger badge-pill sf-alerts-badge">{countResult.numAlerts}</span>}
{countResult && countResult.numAlerts > 0 && <span className="badge btn-danger badge-pill sf-alerts-badge">{countResult.numAlerts}</span>}
</div>
{isOpen && <div className="sf-alerts-toasts">
{alertsGroups == null ? <Toast> <Toast.Body>{JavascriptMessage.loading.niceToString()}</Toast.Body></Toast> :
Expand All @@ -164,7 +164,7 @@ function AlertDropdownImp(props: { checkForChangesEvery: number, keepRingingFor:
<Toast onClose={() => handleOnCloseAlerts(alerts!.map(a=>a))}>
<Toast.Header>
<strong >{AlertMessage._0SimilarAlerts.niceToString(alertsGroups.filter((a, i) => i >= showAlerts).sum(gr => gr.elements.length))}</strong>
<a href="#" className="mr-auto ml-auto" onClick={e => { e.preventDefault(); setShowAlert(a => a + 3); }}><small>{AlertMessage.ViewMore.niceToString()}</small></a>
<a href="#" className="me-auto ms-auto" onClick={e => { e.preventDefault(); setShowAlert(a => a + 3); }}><small>{AlertMessage.ViewMore.niceToString()}</small></a>
<small>{AlertMessage.CloseAll.niceToString()}</small>
</Toast.Header>
</Toast>
Expand Down Expand Up @@ -213,8 +213,8 @@ export function AlertToast(p: { alert: AlertEntity, onClose: (e: AlertEntity[])
return (
<Toast onClose={() => p.onClose([p.alert])} className={p.className}>
<Toast.Header>
{icon && <span className="mr-2">{icon}</span>}
<strong className="mr-auto">{AlertsClient.getTitle(p.alert.titleField, p.alert.alertType)}</strong>
{icon && <span className="me-2">{icon}</span>}
<strong className="me-auto">{AlertsClient.getTitle(p.alert.titleField, p.alert.alertType)}</strong>
<small>{DateTime.fromISO(p.alert.alertDate!).toRelative()}</small>
</Toast.Header>
<Toast.Body style={{ whiteSpace: "pre-wrap" }}>
Expand Down Expand Up @@ -242,9 +242,9 @@ export function AlertGroupToast(p: { alerts: Array<AlertEntity>, onClose: (e: Al
p.alerts.length > showAlerts &&
<Toast className="mt-0" onClose={() => p.onClose(p.alerts)}>
<Toast.Header>
{icon && <span className="mr-2">{icon}</span>}
{icon && <span className="me-2">{icon}</span>}
<strong >{AlertMessage._0SimilarAlerts.niceToString(p.alerts.length - showAlerts)}</strong>
<a href="#" className="mr-auto ml-auto" onClick={e => { e.preventDefault(); setShowAlert(a => a + 3); }}><small>{AlertMessage.ViewMore.niceToString()}</small></a>
<a href="#" className="me-auto ms-auto" onClick={e => { e.preventDefault(); setShowAlert(a => a + 3); }}><small>{AlertMessage.ViewMore.niceToString()}</small></a>
<small>{AlertMessage.CloseAll.niceToString()}</small>
</Toast.Header>
</Toast>
Expand Down
6 changes: 3 additions & 3 deletions Signum.React.Extensions/Alerts/AlertsClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ export function start(options: { routes: JSX.Element[], showAlerts?: (typeName:
}));

Operations.addSettings(new EntityOperationSettings(AlertOperation.Delay, {
onClick: (eoc) => chooseDate().then(d => d && eoc.defaultClick(d.toISO())).done(),
onClick: (eoc) => chooseDate().then(d => d && eoc.defaultClick(d.toISO())),
hideOnCanExecute: true,
contextual: { onClick: (coc) => chooseDate().then(d => d && coc.defaultContextualClick(d.toISO())).done() },
contextualFromMany: { onClick: (coc) => chooseDate().then(d => d && coc.defaultContextualClick(d.toISO())).done() },
contextual: { onClick: (coc) => chooseDate().then(d => d && coc.defaultContextualClick(d.toISO())) },
contextualFromMany: { onClick: (coc) => chooseDate().then(d => d && coc.defaultContextualClick(d.toISO())) },
}));

var cellFormatter = new Finder.CellFormatter((cell, ctx) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function start(options: { routes: JSX.Element[] }) {
return (
{
order: -1,
button: <button className="btn btn-info ml-2"
button: <button className="btn btn-info ms-2"
onClick={e => {
e.preventDefault();
var promise = ValueLineModal.show({
Expand Down
10 changes: 5 additions & 5 deletions Signum.React.Extensions/Authorization/Login/LoginDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ export default function LoginDropdown(p: {
var extraButtons = p.extraButons && p.extraButons(user);

return (
<NavDropdown className="sf-login-dropdown" id="sfLoginDropdown" title={p.renderName ? p.renderName(user) : user.userName!} alignRight >
{pv && <NavDropdown.Item id="sf-auth-profile" onClick={handleProfileClick}><FontAwesomeIcon icon="user-edit" fixedWidth className="mr-2" /> {LoginAuthMessage.MyProfile.niceToString()}</NavDropdown.Item>}
<NavDropdown className="sf-login-dropdown" id="sfLoginDropdown" title={p.renderName ? p.renderName(user) : user.userName!} align="end">
{pv && <NavDropdown.Item id="sf-auth-profile" onClick={handleProfileClick}><FontAwesomeIcon icon="user-edit" fixedWidth className="me-2" /> {LoginAuthMessage.MyProfile.niceToString()}</NavDropdown.Item>}
{cpv && <LinkContainer to="~/auth/changePassword">
<NavDropdown.Item><FontAwesomeIcon icon="key" fixedWidth className="mr-2" /> {LoginAuthMessage.ChangePassword.niceToString()}</NavDropdown.Item>
<NavDropdown.Item><FontAwesomeIcon icon="key" fixedWidth className="me-2" /> {LoginAuthMessage.ChangePassword.niceToString()}</NavDropdown.Item>
</LinkContainer>}
{extraButtons}
{(cpv || pv || extraButtons) && <NavDropdown.Divider />}
{suv && <LinkContainer to="~/auth/login"><NavDropdown.Item><FontAwesomeIcon icon="user-friends" className="mr-2" /> {LoginAuthMessage.SwitchUser.niceToString()}</NavDropdown.Item></LinkContainer>}
<NavDropdown.Item id="sf-auth-logout" onClick={() => AuthClient.logout()}><FontAwesomeIcon icon="sign-out-alt" fixedWidth className="mr-2"/> {LoginAuthMessage.Logout.niceToString()}</NavDropdown.Item>
{suv && <LinkContainer to="~/auth/login"><NavDropdown.Item><FontAwesomeIcon icon="user-friends" className="me-2" /> {LoginAuthMessage.SwitchUser.niceToString()}</NavDropdown.Item></LinkContainer>}
<NavDropdown.Item id="sf-auth-logout" onClick={() => AuthClient.logout()}><FontAwesomeIcon icon="sign-out-alt" fixedWidth className="me-2"/> {LoginAuthMessage.Logout.niceToString()}</NavDropdown.Item>
</NavDropdown>
);
}
Expand Down
39 changes: 18 additions & 21 deletions Signum.React.Extensions/Authorization/Login/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ export default function LoginPage() {
{showLoginForm && <LoginForm ctx={ctx} />}
{LoginPage.customLoginButtons && LoginPage.customLoginButtons(ctx)}
{LoginPage.showLoginForm == "initially_not" && showLoginForm == false &&
<div className="col-md-6 offset-md-3 mt-2">
<a href="#" onClick={e => {
e.preventDefault();
setShowLoginForm(true);
}}>
{LoginAuthMessage.ShowLoginForm.niceToString()}
</a>
<div className="row">
<div className="col-md-6 offset-md-3 mt-2">
<a href="#" className="ms-1" onClick={e => {
e.preventDefault();
setShowLoginForm(true);
}}>
{LoginAuthMessage.ShowLoginForm.niceToString()}
</a>
</div>
</div>
}
</div>
Expand Down Expand Up @@ -110,12 +112,10 @@ export function LoginForm(p: { ctx: LoginContext }) {
</div>
<div className="row">
<div className="col-md-6 offset-md-3">
<div className={classes("form-group", error("userName") && "has-error")}>
<div className={classes("form-group mb-3", error("userName") && "has-error")}>
<label className="sr-only" htmlFor="userName">{LoginAuthMessage.Username.niceToString()}</label>
<div className="input-group mb-2 mr-sm-2 mb-sm-0">
<div className="input-group-prepend">
<div className="input-group-text"><FontAwesomeIcon icon="user" style={{ width: "16px" }} /></div>
</div>
<div className="input-group-text"><FontAwesomeIcon icon="user" style={{ width: "16px" }} /></div>
<input type="text" className="form-control" id="userName" ref={userName} placeholder={LoginAuthMessage.Username.niceToString()} disabled={p.ctx.loading != null} />
</div>
{error("userName") && <span className="help-block text-danger">{error("userName")}</span>}
Expand All @@ -124,12 +124,10 @@ export function LoginForm(p: { ctx: LoginContext }) {
</div>
<div className="row">
<div className="col-md-6 offset-md-3">
<div className={classes("form-group", error("password") && "has-error")}>
<div className={classes("form-group mb-3", error("password") && "has-error")}>
<label className="sr-only" htmlFor="password">{LoginAuthMessage.Password.niceToString()}</label>
<div className="input-group mb-2 mr-sm-2 mb-sm-0">
<div className="input-group-prepend">
<div className="input-group-text"><FontAwesomeIcon icon="key" style={{ width: "16px" }} /></div>
</div>
<div className="input-group-text"><FontAwesomeIcon icon="key" style={{ width: "16px" }} /></div>
<input ref={password} type="password" name="password" className="form-control" id="password" placeholder={LoginAuthMessage.Password.niceToString()} disabled={p.ctx.loading != null} />
</div>
{error("password") && <span className="help-block text-danger">{error("password")}</span>}
Expand All @@ -138,11 +136,10 @@ export function LoginForm(p: { ctx: LoginContext }) {
</div>
{AuthClient.Options.userTicket &&
<div className="row">
<div className="col-md-6 offset-md-3" style={{ paddingTop: ".35rem" }}>
<div className="col-md-6 offset-md-3">
<div className="form-check mb-2 mr-sm-2 mb-sm-0">
<label className="sf-remember-me">
<input ref={rememberMe} name="remember" type="checkbox" disabled={p.ctx.loading != null} /> {LoginAuthMessage.RememberMe.niceToString()}
</label>
<input ref={rememberMe} name="remember" id="rememberMe" className="form-check-input" type="checkbox" disabled={p.ctx.loading != null} />
<label className="sf-remember-me form-check-label" htmlFor="rememberMe" >{LoginAuthMessage.RememberMe.niceToString()}</label>
</div>
</div>
</div>
Expand All @@ -153,15 +150,15 @@ export function LoginForm(p: { ctx: LoginContext }) {
<button type="submit" id="login" className="btn btn-success" disabled={p.ctx.loading != null}>
{p.ctx.loading == "password" ?
<FontAwesomeIcon icon="cog" fixedWidth style={{ fontSize: "larger" }} spin /> : < FontAwesomeIcon icon="sign-in-alt" />}
&nbsp;
&nbsp;
{p.ctx.loading == "password" ? JavascriptMessage.loading.niceToString() : AuthClient.currentUser() ? LoginAuthMessage.SwitchUser.niceToString() : LoginAuthMessage.Login.niceToString()}
</button>
{error("login") && <span className="help-block text-danger" style={{ color: "red" }}>{error("login")}</span>}
{AuthClient.Options.resetPassword && !p.ctx.loading &&
<span>
&nbsp;
&nbsp;
<Link to="~/auth/forgotPasswordEmail">{LoginAuthMessage.IHaveForgottenMyPassword.niceToString()}</Link>
<Link to="~/auth/forgotPasswordEmail">{LoginAuthMessage.IHaveForgottenMyPassword.niceToString()}</Link>
</span>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export function DoublePassword(p: { ctx: TypeContext<string>, isNew: boolean, ma
return (
<div>
<FormGroup ctx={p.ctx} labelText={LoginAuthMessage.NewPassword.niceToString()}>
<input type="password" ref={newPass} autoComplete="off" className={classes(p.ctx.formControlClass, p.mandatory && !newPass.current?.value ? "sf-mandatory" : null)} onBlur={handlePasswordBlur} />
<input type="password" ref={newPass} autoComplete="off" placeholder={LoginAuthMessage.NewPassword.niceToString()} className={classes(p.ctx.formControlClass, p.mandatory && !newPass.current?.value ? "sf-mandatory" : null)} onBlur={handlePasswordBlur} />
</FormGroup>
<FormGroup ctx={p.ctx} labelText={LoginAuthMessage.ConfirmNewPassword.niceToString()}>
<input type="password" ref={newPass2} autoComplete="off" className={classes(p.ctx.formControlClass, p.mandatory && !newPass2.current?.value ? "sf-mandatory" : null)} onBlur={handlePasswordBlur} />
<input type="password" ref={newPass2} autoComplete="off" placeholder={LoginAuthMessage.ConfirmNewPassword.niceToString()} className={classes(p.ctx.formControlClass, p.mandatory && !newPass2.current?.value ? "sf-mandatory" : null)} onBlur={handlePasswordBlur} />
</FormGroup>
</div>
);
Expand Down
3 changes: 1 addition & 2 deletions Signum.React.Extensions/Basics/Templates/CollapsableCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ function isControlled(p: CollapsableCardProps): [boolean, (isOpen: boolean) => v
export default function CollapsableCard(p: CollapsableCardProps) {

const [isOpen, setIsOpen] = isControlled(p);
const isRTL = React.useMemo(() => document.body.classList.contains("rtl"), []);
return (
<div className={classes("card", cardStyleClasses(p.cardStyle), p.size && ("card-" + p.size))}>
<div className={classes("card-header", cardStyleClasses(p.headerStyle))} style={{ cursor: "pointer" }} onClick={() => setIsOpen(!isOpen)}>
{(p.collapsable == undefined || p.collapsable == true) &&
<span
className={isRTL ? "float-left" : "float-right"}
className={"float-end"}
style={{ cursor: "pointer" }}
onClick={() => setIsOpen(!isOpen)}>
<FontAwesomeIcon icon={isOpen ? "chevron-up" : "chevron-down"} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default function PropertyRouteCombo(p : PropertyRouteComboProps){
var routes = p.routes ?? Dic.getValues(getTypeInfo(p.type.cleanName).members).filter(p.filter!).map(mi => PropertyRoute.parse(p.type.cleanName, mi.name));

return (
<select className={ctx.formControlClass} value={ctx.value?.path ?? ""} onChange={handleChange} >
<select className={ctx.formSelectClass} value={ctx.value?.path ?? ""} onChange={handleChange} >
<option value=""> - </option>
{routes.map(r => r.propertyPath()).map(path =>
<option key={path} value={path}>{path}</option>
Expand Down
2 changes: 1 addition & 1 deletion Signum.React.Extensions/Basics/Templates/ScrollPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class ScrollPanel extends React.Component<ScrollPanelProps> {
render() {
return (
<div>
<h3 id={this.props.id}>{this.props.title}&nbsp;{this.props.backId && <Scrollchor to={this.props.backId} className="float-right flip"><small><FontAwesomeIcon icon="level-up" /></small></Scrollchor>}</h3>
<h3 id={this.props.id}>{this.props.title}&nbsp;{this.props.backId && <Scrollchor to={this.props.backId} className="float-end flip"><small><FontAwesomeIcon icon="level-up" /></small></Scrollchor>}</h3>
{this.props.children}
</div>
);
Expand Down
10 changes: 0 additions & 10 deletions Signum.React.Extensions/Chart/Chart.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@

@media (min-width: 1200px) {
body:not(.rtl) .sf-chart-type {
margin-right: -25px;
}

body.rtl .sf-chart-type {
margin-left: -25px;
}
}

.sf-chart-type {
margin-bottom: 4px;
}
Expand Down
12 changes: 6 additions & 6 deletions Signum.React.Extensions/Chart/D3Scripts/Components/ChartUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DateTime, DurationUnit, Duration } from "luxon"
import { DateTime, DurationUnit, Duration, DateTimeUnit } from "luxon"
import * as d3 from "d3"
import * as d3sc from "d3-scale-chromatic";
import { ChartTable, ChartColumn, ChartRow } from "../../ChartClient"
Expand Down Expand Up @@ -141,7 +141,7 @@ export function completeValues(column: ChartColumn<unknown>, values: unknown[],
};
}

function durationUnit(lastPart: string): DurationUnit {
function durationUnit(lastPart: string): DateTimeUnit {
switch (lastPart) {
case "SecondStart": return "second";
case "MinuteStart": return "minute";
Expand All @@ -153,30 +153,30 @@ export function completeValues(column: ChartColumn<unknown>, values: unknown[],
}
}

function tryCeil(date: string | null | undefined, unit: DurationUnit) {
function tryCeil(date: string | null | undefined, unit: DateTimeUnit) {
if (date == null)
return undefined;

return ceil(DateTime.fromISO(date), unit).toISO();
}


function ceil(date: DateTime, unit: DurationUnit) {
function ceil(date: DateTime, unit: DateTimeUnit) {

if (date.toMillis() == date.startOf(unit).toMillis())
return date;

return date.startOf(unit).plus({ [unit]: 1 });
}

function tryFloor(date: string | null | undefined, unit: DurationUnit) {
function tryFloor(date: string | null | undefined, unit: DateTimeUnit) {
if (date == null)
return undefined;

return floor(DateTime.fromISO(date), unit).toISO();
}

function floor(date: DateTime, unit: DurationUnit) {
function floor(date: DateTime, unit: DateTimeUnit) {

return date.startOf(unit);
}
Expand Down
2 changes: 1 addition & 1 deletion Signum.React.Extensions/Chart/Templates/ChartBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export default function ChartBuilder(p: ChartBuilderProps) {
var parameterDic = mlistItemContext(p.ctx.subCtx(c => c.parameters, { formSize: "ExtraSmall", formGroupStyle: "Basic" })).toObject(a => a.value.name!);

return (
<div className="row sf-chart-builder">
<div className="row sf-chart-builder gx-2">
<div className="col-lg-2">
<div className="sf-chart-type card">
<div className="card-header">
Expand Down
Loading

2 comments on commit 7d0804c

@olmobrutall
Copy link
Collaborator Author

@olmobrutall olmobrutall commented on 7d0804c Nov 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bootstrap 5

This commit merges the changes to upgrade all the NPM dependencies, including:

All the Signum components have been migrated to Bootstrap 5 classes, and some Signum Upgrades could help fixing your classe names: Upgrade_20211110_Bootstrap5 and Upgrade_20211112_FixBootstrap, but if you have custom components depending on bootstrap classes you may need to make some fixes.

Some cool additions of Bootstrap 5 are support for RTL and Floating Labels that can not be used with `formGroupStyle: "floatingLabels".

Move to SASS if still using bootstrap.css

Some of the upgrades require changing your custom.scss file, if you are still using plain bootstrap.css you need to do the following:

Bye bye Internet Explorer

Bootstrap 5 is no longer compatible with IE 11 so one of the migrations will change you Index.cshtml to reflect this.

Internet Explorer 11 will be EOL next summer and according represents 0.5% of browser market share.

@MehdyKarimpour
Copy link
Contributor

@MehdyKarimpour MehdyKarimpour commented on 7d0804c Nov 15, 2021 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.