Skip to content

Commit

Permalink
feat: support "label" field for signin item table (#2956)
Browse files Browse the repository at this point in the history
  • Loading branch information
dacongda committed May 18, 2024
1 parent 2daf26a commit 6efec6b
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 40 deletions.
29 changes: 18 additions & 11 deletions object/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type SigninItem struct {
Name string `json:"name"`
Visible bool `json:"visible"`
Label string `json:"label"`
CustomCss string `json:"customCss"`
Placeholder string `json:"placeholder"`
Rule string `json:"rule"`
IsCustom bool `json:"isCustom"`
Expand Down Expand Up @@ -209,92 +210,98 @@ func extendApplicationWithSigninItems(application *Application) (err error) {
signinItem := &SigninItem{
Name: "Back button",
Visible: true,
Label: ".back-button {\n top: 65px;\n left: 15px;\n position: absolute;\n}\n.back-inner-button{}",
CustomCss: ".back-button {\n top: 65px;\n left: 15px;\n position: absolute;\n}\n.back-inner-button{}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Languages",
Visible: true,
Label: ".login-languages {\n top: 55px;\n right: 5px;\n position: absolute;\n}",
CustomCss: ".login-languages {\n top: 55px;\n right: 5px;\n position: absolute;\n}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Logo",
Visible: true,
Label: ".login-logo-box {}",
CustomCss: ".login-logo-box {}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Signin methods",
Visible: true,
Label: ".signin-methods {}",
CustomCss: ".signin-methods {}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Username",
Visible: true,
Label: ".login-username {}\n.login-username-input{}",
CustomCss: ".login-username {}\n.login-username-input{}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Password",
Visible: true,
Label: ".login-password {}\n.login-password-input{}",
CustomCss: ".login-password {}\n.login-password-input{}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Agreement",
Visible: true,
Label: ".login-agreement {}",
CustomCss: ".login-agreement {}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Forgot password?",
Visible: true,
Label: ".login-forget-password {\n display: inline-flex;\n justify-content: space-between;\n width: 320px;\n margin-bottom: 25px;\n}",
CustomCss: ".login-forget-password {\n display: inline-flex;\n justify-content: space-between;\n width: 320px;\n margin-bottom: 25px;\n}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Login button",
Visible: true,
Label: ".login-button-box {\n margin-bottom: 5px;\n}\n.login-button {\n width: 100%;\n}",
CustomCss: ".login-button-box {\n margin-bottom: 5px;\n}\n.login-button {\n width: 100%;\n}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Signup link",
Visible: true,
Label: ".login-signup-link {\n margin-bottom: 24px;\n display: flex;\n justify-content: end;\n}",
CustomCss: ".login-signup-link {\n margin-bottom: 24px;\n display: flex;\n justify-content: end;\n}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
signinItem = &SigninItem{
Name: "Providers",
Visible: true,
Label: ".provider-img {\n width: 30px;\n margin: 5px;\n}\n.provider-big-img {\n margin-bottom: 10px;\n}",
CustomCss: ".provider-img {\n width: 30px;\n margin: 5px;\n}\n.provider-big-img {\n margin-bottom: 10px;\n}",
Placeholder: "",
Rule: "None",
}
application.SigninItems = append(application.SigninItems, signinItem)
}
for idx, item := range application.SigninItems {
if item.Label != "" && item.CustomCss == "" {
application.SigninItems[idx].CustomCss = item.Label
application.SigninItems[idx].Label = ""
}
}
return
}

Expand Down
51 changes: 28 additions & 23 deletions web/src/auth/LoginPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ class LoginPage extends React.Component {
if (signinItem.name === "Logo") {
return (
<div className="login-logo-box">
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
{
Setting.renderHelmet(application)
}
Expand All @@ -544,7 +544,7 @@ class LoginPage extends React.Component {
} else if (signinItem.name === "Back button") {
return (
<div className="back-button">
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
{
this.renderBackButton()
}
Expand All @@ -562,25 +562,26 @@ class LoginPage extends React.Component {

return (
<div className="login-languages">
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<LanguageSelect languages={application.organizationObj.languages} />
</div>
);
} else if (signinItem.name === "Signin methods") {
return (
<div>
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
{this.renderMethodChoiceBox()}
</div>
)
;
} else if (signinItem.name === "Username") {
return (
<div>
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<Form.Item
name="username"
className="login-username"
label={signinItem.label ? signinItem.label : null}
rules={[
{
required: true,
Expand Down Expand Up @@ -653,22 +654,22 @@ class LoginPage extends React.Component {
} else if (signinItem.name === "Password") {
return (
<div>
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
{this.renderPasswordOrCodeInput()}
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
{this.renderPasswordOrCodeInput(signinItem)}
</div>
);
} else if (signinItem.name === "Forgot password?") {
return (
<div>
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div className="login-forget-password">
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
<Checkbox style={{float: "left"}}>
{i18next.t("login:Auto sign in")}
</Checkbox>
</Form.Item>
{
signinItem.visible ? Setting.renderForgetLink(application, i18next.t("login:Forgot password?")) : null
signinItem.visible ? Setting.renderForgetLink(application, signinItem.label ? signinItem.label : i18next.t("login:Forgot password?")) : null
}
</div>
</div>
Expand All @@ -678,7 +679,7 @@ class LoginPage extends React.Component {
} else if (signinItem.name === "Login button") {
return (
<Form.Item className="login-button-box">
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<Button
type="primary"
htmlType="submit"
Expand All @@ -687,7 +688,7 @@ class LoginPage extends React.Component {
{
this.state.loginMethod === "webAuthn" ? i18next.t("login:Sign in with WebAuthn") :
this.state.loginMethod === "faceId" ? i18next.t("login:Sign in with Face ID") :
i18next.t("login:Sign In")
signinItem.label ? signinItem.label : i18next.t("login:Sign In")
}
</Button>
{
Expand Down Expand Up @@ -722,7 +723,7 @@ class LoginPage extends React.Component {

return (
<div>
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<Form.Item>
{
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
Expand All @@ -737,13 +738,13 @@ class LoginPage extends React.Component {
);
} else if (signinItem.name.startsWith("Text ") || signinItem?.isCustom) {
return (
<div dangerouslySetInnerHTML={{__html: signinItem.label}} />
<div dangerouslySetInnerHTML={{__html: signinItem.customCss}} />
);
} else if (signinItem.name === "Signup link") {
return (
<div style={{width: "100%"}} className="login-signup-link">
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.label?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
{this.renderFooter(application)}
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
{this.renderFooter(application, signinItem)}
</div>
);
}
Expand Down Expand Up @@ -896,17 +897,20 @@ class LoginPage extends React.Component {
/>;
}

renderFooter(application) {
renderFooter(application, signinItem) {
return (
<div>
{
!application.enableSignUp ? null : (
<React.Fragment>
{i18next.t("login:No account?")}&nbsp;
{
Setting.renderSignupLink(application, i18next.t("login:sign up now"))
}
</React.Fragment>
signinItem.label ? Setting.renderSignupLink(application, signinItem.label) :
(
<React.Fragment>
{i18next.t("login:No account?")}
{
Setting.renderSignupLink(application, i18next.t("login:sign up now"))
}
</React.Fragment>
)
)
}
</div>
Expand Down Expand Up @@ -1022,7 +1026,7 @@ class LoginPage extends React.Component {
});
}

renderPasswordOrCodeInput() {
renderPasswordOrCodeInput(signinItem) {
const application = this.getApplicationObj();
if (this.state.loginMethod === "password" || this.state.loginMethod === "ldap") {
return (
Expand All @@ -1031,6 +1035,7 @@ class LoginPage extends React.Component {
<Form.Item
name="password"
className="login-password"
label={signinItem.label ? signinItem.label : null}
rules={[{required: true, message: i18next.t("login:Please input your password!")}]}
>
<Input.Password
Expand Down
16 changes: 10 additions & 6 deletions web/src/table/SigninTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class SigninTable extends React.Component {
value={getItemDisplayName(text)}
onChange={value => {
this.updateField(table, index, "name", value);
this.updateField(table, index, "label", SigninTableDefaultCssMap[value]);
this.updateField(table, index, "customCss", SigninTableDefaultCssMap[value]);
}} >
{
Setting.getDeduplicatedArray(items, table, "name").map((item, index) => <Option key={index} value={item.name}>{item.displayName}</Option>)
Expand Down Expand Up @@ -166,7 +166,7 @@ class SigninTable extends React.Component {
},
},
{
title: i18next.t("signup:Label HTML"),
title: i18next.t("signup:Label"),
dataIndex: "label",
key: "label",
width: "200px",
Expand All @@ -188,14 +188,18 @@ class SigninTable extends React.Component {
}} />
</Popover>
);
} else if (["Username", "Password", "Signup link", "Forgot password?", "Login button"].includes(record.name)) {
return <Input value={text} style={{marginBottom: "10px"}} onChange={e => {
this.updateField(table, index, "label", e.target.value);
}} />;
}
return null;
},
},
{
title: i18next.t("application:Custom CSS"),
dataIndex: "label",
key: "label",
dataIndex: "customCss",
key: "customCss",
width: "200px",
render: (text, record, index) => {
if (!record.name.startsWith("Text ") && !record?.isCustom) {
Expand All @@ -205,13 +209,13 @@ class SigninTable extends React.Component {
<CodeMirror value={text?.replaceAll("<style>", "").replaceAll("</style>", "")}
options={{mode: "css", theme: "material-darker"}}
onBeforeChange={(editor, data, value) => {
this.updateField(table, index, "label", value);
this.updateField(table, index, "customCss", value);
}}
/>
</div>
} title={i18next.t("application:CSS style")} trigger="click">
<Input value={text?.replaceAll("<style>", "").replaceAll("</style>", "")} onChange={e => {
this.updateField(table, index, "label", e.target.value);
this.updateField(table, index, "customCss", e.target.value);
}} />
</Popover>
);
Expand Down

0 comments on commit 6efec6b

Please sign in to comment.