mirror of https://github.com/zulip/zulip.git
custom_profile_fields: Support non editable profile fields.
This commit allows configuration of "editable_by_user" property from the organization settings modal. It also adds support for non-editable fields in profile settings modal. Fixes #22883. Co-Authored-By: Ujjawal Modi <umodi2003@gmail.com>
This commit is contained in:
parent
fc5cdd9e83
commit
23efb5cec7
|
@ -98,6 +98,26 @@ it out.
|
||||||
|
|
||||||
{end_tabs}
|
{end_tabs}
|
||||||
|
|
||||||
|
## Configure whether users can edit custom profile fields
|
||||||
|
|
||||||
|
{!admin-only.md!}
|
||||||
|
|
||||||
|
You can configure whether users in your organization can modify their
|
||||||
|
own custom profile fields. For example, you may want to restrict editing
|
||||||
|
if syncing profile fields from an employee directory.
|
||||||
|
|
||||||
|
{start_tabs}
|
||||||
|
|
||||||
|
{settings_tab|profile-field-settings}
|
||||||
|
|
||||||
|
1. In the **Actions** column, click the **pencil** (<i class="fa fa-pencil"></i>)
|
||||||
|
icon for the profile field you want to configure.
|
||||||
|
|
||||||
|
1. Toggle **Users can edit this field**.
|
||||||
|
|
||||||
|
4. Click **Save changes**.
|
||||||
|
|
||||||
|
{end_tabs}
|
||||||
|
|
||||||
## Profile field types
|
## Profile field types
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {$t} from "./i18n";
|
||||||
import * as people from "./people";
|
import * as people from "./people";
|
||||||
import * as pill_typeahead from "./pill_typeahead";
|
import * as pill_typeahead from "./pill_typeahead";
|
||||||
import * as settings_components from "./settings_components";
|
import * as settings_components from "./settings_components";
|
||||||
import {realm} from "./state_data";
|
import {current_user, realm} from "./state_data";
|
||||||
import * as typeahead_helper from "./typeahead_helper";
|
import * as typeahead_helper from "./typeahead_helper";
|
||||||
import type {UserPillWidget} from "./user_pill";
|
import type {UserPillWidget} from "./user_pill";
|
||||||
import * as user_pill from "./user_pill";
|
import * as user_pill from "./user_pill";
|
||||||
|
@ -38,6 +38,7 @@ export function append_custom_profile_fields(element_id: string, user_id: number
|
||||||
|
|
||||||
for (const field of all_custom_fields) {
|
for (const field of all_custom_fields) {
|
||||||
let field_value = people.get_custom_profile_data(user_id, field.id);
|
let field_value = people.get_custom_profile_data(user_id, field.id);
|
||||||
|
const editable_by_user = current_user.is_admin || field.editable_by_user;
|
||||||
const is_select_field = field.type === all_field_types.SELECT.id;
|
const is_select_field = field.type === all_field_types.SELECT.id;
|
||||||
const field_choices = [];
|
const field_choices = [];
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ export function append_custom_profile_fields(element_id: string, user_id: number
|
||||||
field_choices,
|
field_choices,
|
||||||
for_manage_user_modal: element_id === "#edit-user-form .custom-profile-field-form",
|
for_manage_user_modal: element_id === "#edit-user-form .custom-profile-field-form",
|
||||||
is_empty_required_field: field.required && !field_value.value,
|
is_empty_required_field: field.required && !field_value.value,
|
||||||
|
editable_by_user,
|
||||||
});
|
});
|
||||||
$(element_id).append($(html));
|
$(element_id).append($(html));
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,6 +242,7 @@ function open_custom_profile_field_form_modal(): void {
|
||||||
":checked",
|
":checked",
|
||||||
),
|
),
|
||||||
required: $("#profile-field-required").is(":checked"),
|
required: $("#profile-field-required").is(":checked"),
|
||||||
|
editable_by_user: $("#profile_field_editable_by_user").is(":checked"),
|
||||||
};
|
};
|
||||||
const url = "/json/realm/profile_fields";
|
const url = "/json/realm/profile_fields";
|
||||||
const opts = {
|
const opts = {
|
||||||
|
@ -461,6 +462,7 @@ function open_edit_form_modal(this: HTMLElement): void {
|
||||||
choices,
|
choices,
|
||||||
display_in_profile_summary: field.display_in_profile_summary === true,
|
display_in_profile_summary: field.display_in_profile_summary === true,
|
||||||
required: field.required,
|
required: field.required,
|
||||||
|
editable_by_user: field.editable_by_user,
|
||||||
is_select_field: field.type === field_types.SELECT.id,
|
is_select_field: field.type === field_types.SELECT.id,
|
||||||
is_external_account_field: field.type === field_types.EXTERNAL_ACCOUNT.id,
|
is_external_account_field: field.type === field_types.EXTERNAL_ACCOUNT.id,
|
||||||
valid_to_display_in_summary: is_valid_to_display_in_summary(field.type),
|
valid_to_display_in_summary: is_valid_to_display_in_summary(field.type),
|
||||||
|
|
|
@ -34,6 +34,7 @@ export type NarrowTerm = z.output<typeof narrow_term_schema>;
|
||||||
|
|
||||||
export const custom_profile_field_schema = z.object({
|
export const custom_profile_field_schema = z.object({
|
||||||
display_in_profile_summary: z.optional(z.boolean()),
|
display_in_profile_summary: z.optional(z.boolean()),
|
||||||
|
editable_by_user: z.boolean(),
|
||||||
field_data: z.string(),
|
field_data: z.string(),
|
||||||
hint: z.string(),
|
hint: z.string(),
|
||||||
id: z.number(),
|
id: z.number(),
|
||||||
|
|
|
@ -762,6 +762,18 @@ export function initialize(): void {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tippy.delegate("body", {
|
||||||
|
target: ".settings-profile-user-field.not-editable-by-user-input-wrapper",
|
||||||
|
content: $t({
|
||||||
|
defaultMessage:
|
||||||
|
"You are not allowed to change this field. Contact an administrator to update it.",
|
||||||
|
}),
|
||||||
|
appendTo: () => document.body,
|
||||||
|
onHidden(instance) {
|
||||||
|
instance.destroy();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
tippy.delegate("body", {
|
tippy.delegate("body", {
|
||||||
target: ".popover-contains-shift-hotkey",
|
target: ".popover-contains-shift-hotkey",
|
||||||
trigger: "mouseenter",
|
trigger: "mouseenter",
|
||||||
|
|
|
@ -409,6 +409,10 @@
|
||||||
.pill-container {
|
.pill-container {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
|
|
||||||
|
&.not-editable-by-user {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-profile-user-field {
|
.settings-profile-user-field {
|
||||||
|
|
|
@ -164,6 +164,19 @@
|
||||||
perspective: 1000px;
|
perspective: 1000px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.not-editable-by-user {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background-color: hsl(0deg 0% 93%);
|
||||||
|
|
||||||
|
.pill {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#compose-direct-recipient .pill-container {
|
#compose-direct-recipient .pill-container {
|
||||||
|
|
|
@ -1545,6 +1545,10 @@ $option_title_width: 180px;
|
||||||
.datepicker {
|
.datepicker {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& input[disabled].datepicker {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#show_my_user_profile_modal {
|
#show_my_user_profile_modal {
|
||||||
|
@ -1988,6 +1992,11 @@ $option_title_width: 180px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Needed for settings_checkbox partial. */
|
||||||
|
.inline {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#admin_users_table .deactivated_user,
|
#admin_users_table .deactivated_user,
|
||||||
|
|
|
@ -50,5 +50,11 @@
|
||||||
{{t 'Required field' }}
|
{{t 'Required field' }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
{{> settings_checkbox
|
||||||
|
prefix="profile_field_"
|
||||||
|
setting_name="editable_by_user"
|
||||||
|
is_checked=true
|
||||||
|
label=(t "Users can edit this field")
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -5,30 +5,30 @@
|
||||||
</span>
|
</span>
|
||||||
<div class="alert-notification custom-field-status"></div>
|
<div class="alert-notification custom-field-status"></div>
|
||||||
<div class="settings-profile-user-field-hint">{{ field.hint }}</div>
|
<div class="settings-profile-user-field-hint">{{ field.hint }}</div>
|
||||||
<div class="settings-profile-user-field {{#if is_empty_required_field}}empty-required-field{{/if}}">
|
<div class="settings-profile-user-field {{#if is_empty_required_field}}empty-required-field{{/if}} {{#unless editable_by_user}}not-editable-by-user-input-wrapper{{/unless}}">
|
||||||
{{#if is_long_text_field}}
|
{{#if is_long_text_field}}
|
||||||
<textarea maxlength="500" class="custom_user_field_value settings_textarea" name="{{ field.id }}">{{ field_value.value }}</textarea>
|
<textarea maxlength="500" class="custom_user_field_value settings_textarea" name="{{ field.id }}" {{#unless editable_by_user}}disabled{{/unless}}>{{ field_value.value }}</textarea>
|
||||||
{{else if is_select_field}}
|
{{else if is_select_field}}
|
||||||
<select class="custom_user_field_value {{#if for_manage_user_modal}}modal_select{{else}}settings_select{{/if}} bootstrap-focus-style" name="{{ field.id }}">
|
<select class="custom_user_field_value {{#if for_manage_user_modal}}modal_select{{else}}settings_select{{/if}} bootstrap-focus-style" name="{{ field.id }}" {{#unless editable_by_user}}disabled{{/unless}}>
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
{{#each field_choices}}
|
{{#each field_choices}}
|
||||||
<option value="{{ this.value }}" {{#if this.selected}}selected{{/if}}>{{ this.text }}</option>
|
<option value="{{ this.value }}" {{#if this.selected}}selected{{/if}}>{{ this.text }}</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
{{else if is_user_field }}
|
{{else if is_user_field }}
|
||||||
<div class="pill-container person_picker" name="{{ field.id }}">
|
<div class="pill-container person_picker {{#unless editable_by_user}}not-editable-by-user disabled{{/unless}}" name="{{ field.id }}">
|
||||||
<div class="input" contenteditable="true"></div>
|
<div class="input" {{#if editable_by_user}}contenteditable="true"{{/if}}></div>
|
||||||
</div>
|
</div>
|
||||||
{{else if is_date_field }}
|
{{else if is_date_field }}
|
||||||
<input class="custom_user_field_value datepicker {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" data-field-id="{{ field.id }}" type="text"
|
<input class="custom_user_field_value datepicker {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" data-field-id="{{ field.id }}" type="text"
|
||||||
value="{{ field_value.value }}" />
|
value="{{ field_value.value }}" {{#unless editable_by_user}}disabled{{/unless}}/>
|
||||||
<span class="remove_date"><i class="fa fa-close"></i></span>
|
{{#if editable_by_user}}<span class="remove_date"><i class="fa fa-close"></i></span>{{/if}}
|
||||||
{{else if is_url_field }}
|
{{else if is_url_field }}
|
||||||
<input class="custom_user_field_value {{#if for_manage_user_modal}}modal_url_input{{else}}settings_url_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="2048" />
|
<input class="custom_user_field_value {{#if for_manage_user_modal}}modal_url_input{{else}}settings_url_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="2048" {{#unless editable_by_user}}disabled{{/unless}}/>
|
||||||
{{else if is_pronouns_field}}
|
{{else if is_pronouns_field}}
|
||||||
<input class="custom_user_field_value pronouns_type_field {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="50" />
|
<input class="custom_user_field_value pronouns_type_field {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="50" {{#unless editable_by_user}}disabled{{/unless}}/>
|
||||||
{{else}}
|
{{else}}
|
||||||
<input class="custom_user_field_value {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="50" />
|
<input class="custom_user_field_value {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="50" {{#unless editable_by_user}}disabled{{/unless}}/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -52,5 +52,11 @@
|
||||||
{{t 'Required field' }}
|
{{t 'Required field' }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
{{> settings_checkbox
|
||||||
|
prefix="id-custom-profile-field-"
|
||||||
|
setting_name="editable-by-user"
|
||||||
|
is_checked= editable_by_user
|
||||||
|
label=(t "Users can edit this field")
|
||||||
|
}}
|
||||||
</form>
|
</form>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
|
|
Loading…
Reference in New Issue