Merge pull request #81 from shariquerik/fields-display-rules

feat: Permissions & Field Visibility
This commit is contained in:
Shariq Ansari 2024-03-20 16:52:31 +05:30 committed by GitHub
commit 9b018c29ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 56 additions and 5 deletions

View File

@ -244,7 +244,7 @@ def get_list_data(
} }
def get_doctype_fields(doctype): def get_doctype_fields(doctype, name):
not_allowed_fieldtypes = [ not_allowed_fieldtypes = [
"Section Break", "Section Break",
"Column Break", "Column Break",
@ -256,6 +256,12 @@ def get_doctype_fields(doctype):
sections = {} sections = {}
section_fields = [] section_fields = []
last_section = None last_section = None
doc = frappe.get_cached_doc(doctype, name)
has_high_permlevel_fields = any(df.permlevel > 0 for df in fields)
if has_high_permlevel_fields:
has_read_access_to_permlevels = doc.get_permlevel_access("read")
has_write_access_to_permlevels = doc.get_permlevel_access("write")
for field in fields: for field in fields:
if field.fieldtype == "Tab Break" and last_section: if field.fieldtype == "Tab Break" and last_section:
@ -277,6 +283,13 @@ def get_doctype_fields(doctype):
"fields": [], "fields": [],
} }
else: else:
if field.permlevel > 0:
field_has_write_access = field.permlevel in has_write_access_to_permlevels
field_has_read_access = field.permlevel in has_read_access_to_permlevels
if not field_has_write_access and field_has_read_access:
field.read_only = 1
if not field_has_read_access and not field_has_write_access:
field.hidden = 1
section_fields.append(get_field_obj(field)) section_fields.append(get_field_obj(field))
section_fields = [] section_fields = []
@ -299,6 +312,7 @@ def get_field_obj(field):
"hidden": field.hidden, "hidden": field.hidden,
"reqd": field.reqd, "reqd": field.reqd,
"read_only": field.read_only, "read_only": field.read_only,
"all_properties": field,
} }
obj["placeholder"] = "Add " + field.label + "..." obj["placeholder"] = "Add " + field.label + "..."

View File

@ -27,7 +27,7 @@ def get_deal(name):
fields=["contact", "is_primary"], fields=["contact", "is_primary"],
) )
deal["doctype_fields"], deal["all_fields"] = get_doctype_fields("CRM Deal") deal["doctype_fields"], deal["all_fields"] = get_doctype_fields("CRM Deal", name)
deal["doctype"] = "CRM Deal" deal["doctype"] = "CRM Deal"
deal["_form_script"] = get_form_script('CRM Deal') deal["_form_script"] = get_form_script('CRM Deal')
deal["_assign"] = get_assigned_users("CRM Deal", deal.name) deal["_assign"] = get_assigned_users("CRM Deal", deal.name)

View File

@ -15,7 +15,7 @@ def get_lead(name):
frappe.throw(_("Lead not found"), frappe.DoesNotExistError) frappe.throw(_("Lead not found"), frappe.DoesNotExistError)
lead = lead.pop() lead = lead.pop()
lead["doctype_fields"], lead["all_fields"] = get_doctype_fields("CRM Lead") lead["doctype_fields"], lead["all_fields"] = get_doctype_fields("CRM Lead", name)
lead["doctype"] = "CRM Lead" lead["doctype"] = "CRM Lead"
lead["_form_script"] = get_form_script('CRM Lead') lead["_form_script"] = get_form_script('CRM Lead')
lead["_assign"] = get_assigned_users("CRM Lead", lead.name) lead["_assign"] = get_assigned_users("CRM Lead", lead.name)

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="flex max-h-[300px] flex-col gap-1.5 overflow-y-auto"> <div class="flex max-h-[300px] flex-col gap-1.5 overflow-y-auto">
<div <div
v-for="field in fields" v-for="field in _fields"
:key="field.label" :key="field.label"
:class="[field.hidden && 'hidden']" :class="[field.hidden && 'hidden']"
class="flex items-center gap-2 px-3 leading-5 first:mt-3" class="flex items-center gap-2 px-3 leading-5 first:mt-3"
@ -109,7 +109,7 @@ import Link from '@/components/Controls/Link.vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import { usersStore } from '@/stores/users' import { usersStore } from '@/stores/users'
import { Tooltip } from 'frappe-ui' import { Tooltip } from 'frappe-ui'
import { defineModel } from 'vue' import { computed } from 'vue'
const props = defineProps({ const props = defineProps({
fields: { fields: {
@ -123,6 +123,43 @@ const { getUser } = usersStore()
const emit = defineEmits(['update']) const emit = defineEmits(['update'])
const data = defineModel() const data = defineModel()
const _fields = computed(() => {
let all_fields = []
props.fields?.forEach((field) => {
let df = field.all_properties
if (df.depends_on) evaluate_depends_on(df.depends_on, field)
all_fields.push(field)
})
return all_fields
})
function evaluate_depends_on(expression, field) {
if (expression.substr(0, 5) == 'eval:') {
try {
let out = evaluate(expression.substr(5), { doc: data.value })
if (!out) {
field.hidden = true
}
} catch (e) {
console.error(e)
}
}
}
function evaluate(code, context = {}) {
let variable_names = Object.keys(context)
let variables = Object.values(context)
code = `let out = ${code}; return out`
try {
let expression_function = new Function(...variable_names, code)
return expression_function(...variables)
} catch (error) {
console.log('Error evaluating the following expression:')
console.error(code)
throw error
}
}
</script> </script>
<style scoped> <style scoped>