fix: refactored job form and permissions
This commit is contained in:
@@ -107,7 +107,7 @@
|
|||||||
<div class="flex flex-col gap-1 p-1">
|
<div class="flex flex-col gap-1 p-1">
|
||||||
<div class="text-base font-medium text-ink-gray-8">
|
<div class="text-base font-medium text-ink-gray-8">
|
||||||
{{
|
{{
|
||||||
option.value == option.label
|
option.value == option.label && option.description
|
||||||
? option.description
|
? option.description
|
||||||
: option.label
|
: option.label
|
||||||
}}
|
}}
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
v-if="groups.length == 0"
|
v-if="groups.length == 0"
|
||||||
class="mt-1.5 rounded-md px-2.5 py-1.5 text-base text-ink-gray-5"
|
class="mt-1.5 rounded-md px-2.5 py-1.5 text-base text-ink-gray-5"
|
||||||
>
|
>
|
||||||
No results found
|
{{ __('No results found') }}
|
||||||
</li>
|
</li>
|
||||||
</ComboboxOptions>
|
</ComboboxOptions>
|
||||||
<div v-if="slots.footer" class="border-t p-1.5 pb-0.5">
|
<div v-if="slots.footer" class="border-t p-1.5 pb-0.5">
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
'border object-cover',
|
'border object-cover',
|
||||||
shape === 'circle'
|
shape === 'circle'
|
||||||
? 'w-20 h-20 rounded-full'
|
? 'w-20 h-20 rounded-full'
|
||||||
: 'w-44 h-auto min-h-20 rounded-md',
|
: 'w-44 h-auto min-h-20 max-h-32 rounded-md',
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
<video v-else controls class="border rounded-md w-44 h-auto">
|
<video v-else controls class="border rounded-md w-44 h-auto">
|
||||||
|
|||||||
@@ -6,16 +6,18 @@
|
|||||||
<div class="text-xl font-semibold leading-none text-ink-gray-9">
|
<div class="text-xl font-semibold leading-none text-ink-gray-9">
|
||||||
{{ __(label) }}
|
{{ __(label) }}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="space-x-2">
|
||||||
<Badge
|
<Badge
|
||||||
v-if="data.isDirty"
|
v-if="data.isDirty"
|
||||||
:label="__('Not Saved')"
|
:label="__('Not Saved')"
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
theme="orange"
|
theme="orange"
|
||||||
/>
|
/>
|
||||||
|
<Button variant="solid" :loading="data.save.loading" @click="update">
|
||||||
|
{{ __('Update') }}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="solid" :loading="data.save.loading" @click="update">
|
|
||||||
{{ __('Update') }}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="text-ink-gray-6 leading-5">
|
<div class="text-ink-gray-6 leading-5">
|
||||||
{{ __(description) }}
|
{{ __(description) }}
|
||||||
|
|||||||
@@ -219,6 +219,25 @@ const tabsStructure = computed(() => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Jobs',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
label: 'Allow Job Posting',
|
||||||
|
name: 'allow_job_posting',
|
||||||
|
type: 'checkbox',
|
||||||
|
description:
|
||||||
|
'If enabled, users can post job openings on the job board. Else only admins can post jobs.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fields: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
columns: [
|
columns: [
|
||||||
|
|||||||
+126
-107
@@ -4,9 +4,14 @@
|
|||||||
class="sticky top-0 z-10 flex items-center justify-between border-b bg-surface-white px-3 py-2.5 sm:px-5"
|
class="sticky top-0 z-10 flex items-center justify-between border-b bg-surface-white px-3 py-2.5 sm:px-5"
|
||||||
>
|
>
|
||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
<Button variant="solid" @click="saveJob()">
|
<div class="space-x-2">
|
||||||
{{ __('Save') }}
|
<Badge v-if="isDirty" theme="orange">
|
||||||
</Button>
|
{{ __('Not Saved') }}
|
||||||
|
</Badge>
|
||||||
|
<Button variant="solid" @click="saveJob()">
|
||||||
|
{{ __('Save') }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="py-5">
|
<div class="py-5">
|
||||||
<div class="container border-b mb-4 pb-5">
|
<div class="container border-b mb-4 pb-5">
|
||||||
@@ -109,15 +114,25 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
|
Badge,
|
||||||
Breadcrumbs,
|
Breadcrumbs,
|
||||||
|
call,
|
||||||
FormControl,
|
FormControl,
|
||||||
createResource,
|
createDocumentResource,
|
||||||
Button,
|
Button,
|
||||||
TextEditor,
|
TextEditor,
|
||||||
usePageMeta,
|
usePageMeta,
|
||||||
toast,
|
toast,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { computed, onMounted, reactive, inject } from 'vue'
|
import {
|
||||||
|
computed,
|
||||||
|
inject,
|
||||||
|
onMounted,
|
||||||
|
onBeforeUnmount,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
import { sessionStore } from '@/stores/session'
|
import { sessionStore } from '@/stores/session'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { escapeHTML, sanitizeHTML } from '@/utils'
|
import { escapeHTML, sanitizeHTML } from '@/utils'
|
||||||
@@ -126,6 +141,8 @@ import Uploader from '@/components/Controls/Uploader.vue'
|
|||||||
const user = inject('$user')
|
const user = inject('$user')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { brand } = sessionStore()
|
const { brand } = sessionStore()
|
||||||
|
const isDirty = ref(false)
|
||||||
|
const originalJobData = ref(null)
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
jobName: {
|
jobName: {
|
||||||
@@ -134,67 +151,6 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const newJob = createResource({
|
|
||||||
url: 'frappe.client.insert',
|
|
||||||
makeParams(values) {
|
|
||||||
return {
|
|
||||||
doc: {
|
|
||||||
doctype: 'Job Opportunity',
|
|
||||||
company_logo: job.company_logo,
|
|
||||||
...job,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const updateJob = createResource({
|
|
||||||
url: 'frappe.client.set_value',
|
|
||||||
makeParams(values) {
|
|
||||||
return {
|
|
||||||
doctype: 'Job Opportunity',
|
|
||||||
name: props.jobName,
|
|
||||||
fieldname: {
|
|
||||||
company_logo: job.company_logo,
|
|
||||||
...job,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const jobDetail = createResource({
|
|
||||||
url: 'frappe.client.get',
|
|
||||||
makeParams(values) {
|
|
||||||
return {
|
|
||||||
doctype: 'Job Opportunity',
|
|
||||||
name: props.jobName,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSuccess(data) {
|
|
||||||
if (data.owner != user.data?.name && !user.data?.is_moderator) {
|
|
||||||
router.push({
|
|
||||||
name: 'Jobs',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Object.keys(data).forEach((key) => {
|
|
||||||
if (Object.hasOwn(job, key)) job[key] = data[key]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const job = reactive({
|
|
||||||
job_title: '',
|
|
||||||
location: '',
|
|
||||||
country: '',
|
|
||||||
type: 'Full Time',
|
|
||||||
work_mode: 'On-site',
|
|
||||||
status: 'Open',
|
|
||||||
company_name: '',
|
|
||||||
company_website: '',
|
|
||||||
company_logo: null,
|
|
||||||
description: '',
|
|
||||||
company_email_address: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!user.data) {
|
if (!user.data) {
|
||||||
router.push({
|
router.push({
|
||||||
@@ -202,22 +158,63 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.jobName != 'new') jobDetail.reload()
|
if (props.jobName != 'new') jobDetails.reload()
|
||||||
addKeyboardShortcuts()
|
window.addEventListener('keydown', keyboardShortcut)
|
||||||
})
|
})
|
||||||
|
|
||||||
const addKeyboardShortcuts = () => {
|
const job = reactive({
|
||||||
document.addEventListener('keydown', (e) => {
|
job_title: '',
|
||||||
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 's') {
|
type: '',
|
||||||
e.preventDefault()
|
work_mode: '',
|
||||||
saveJob()
|
location: '',
|
||||||
|
country: '',
|
||||||
|
status: 'Open',
|
||||||
|
description: '',
|
||||||
|
company_name: '',
|
||||||
|
company_website: '',
|
||||||
|
company_email_address: '',
|
||||||
|
company_logo: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const jobDetails = createDocumentResource({
|
||||||
|
doctype: 'Job Opportunity',
|
||||||
|
name: props.jobName != 'new' ? props.jobName : undefined,
|
||||||
|
onError(err) {
|
||||||
|
toast.error(err.messages?.[0] || err)
|
||||||
|
console.error(err)
|
||||||
|
},
|
||||||
|
auto: props.jobName != 'new',
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => jobDetails?.doc,
|
||||||
|
() => {
|
||||||
|
if (jobDetails.doc.owner != user.data?.name && !user.data?.is_moderator) {
|
||||||
|
router.push({
|
||||||
|
name: 'Jobs',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
if (jobDetails.doc) {
|
||||||
|
Object.assign(job, jobDetails.doc)
|
||||||
|
originalJobData.value = JSON.parse(JSON.stringify(jobDetails.doc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
job,
|
||||||
|
() => {
|
||||||
|
isDirty.value = Object.keys(job).some((key) => {
|
||||||
|
return job[key] != originalJobData.value?.[key]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
const saveJob = () => {
|
const saveJob = () => {
|
||||||
validateJobFields()
|
validateJobFields()
|
||||||
if (jobDetail.data) {
|
if (jobDetails?.doc) {
|
||||||
editJobDetails()
|
editJobDetails()
|
||||||
} else {
|
} else {
|
||||||
createNewJob()
|
createNewJob()
|
||||||
@@ -225,38 +222,46 @@ const saveJob = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const createNewJob = () => {
|
const createNewJob = () => {
|
||||||
newJob.submit(
|
call('frappe.client.insert', {
|
||||||
{},
|
doc: {
|
||||||
{
|
doctype: 'Job Opportunity',
|
||||||
onSuccess(data) {
|
company_logo: job.company_logo,
|
||||||
router.push({
|
...job,
|
||||||
name: 'JobDetail',
|
},
|
||||||
params: {
|
})
|
||||||
job: data.name,
|
.then((data) => {
|
||||||
},
|
router.push({
|
||||||
})
|
name: 'JobDetail',
|
||||||
},
|
params: {
|
||||||
onError(err) {
|
job: data.name,
|
||||||
toast.error(err.messages?.[0] || err)
|
},
|
||||||
},
|
})
|
||||||
}
|
})
|
||||||
)
|
.catch((err) => {
|
||||||
|
toast.error(err.messages?.[0] || err)
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const editJobDetails = () => {
|
const editJobDetails = () => {
|
||||||
updateJob.submit(
|
jobDetails.setValue.submit(
|
||||||
{},
|
{
|
||||||
|
company_logo: job.company_logo,
|
||||||
|
...job,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
onSuccess(data) {
|
onSuccess(data) {
|
||||||
|
jobDetails.reload()
|
||||||
router.push({
|
router.push({
|
||||||
name: 'JobDetail',
|
name: 'JobDetail',
|
||||||
params: {
|
params: {
|
||||||
job: data.name,
|
job: props.jobName,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onError(err) {
|
onError(err) {
|
||||||
toast.error(err.messages?.[0] || err)
|
toast.error(err.messages?.[0] || err)
|
||||||
|
console.error(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -271,27 +276,38 @@ const validateJobFields = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keyboardShortcut = (e) => {
|
||||||
|
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 's') {
|
||||||
|
e.preventDefault()
|
||||||
|
saveJob()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('keydown', keyboardShortcut)
|
||||||
|
})
|
||||||
|
|
||||||
const jobTypes = computed(() => {
|
const jobTypes = computed(() => {
|
||||||
return [
|
return [
|
||||||
{ label: 'Full Time', value: 'Full Time' },
|
{ label: __('Full Time'), value: 'Full Time' },
|
||||||
{ label: 'Part Time', value: 'Part Time' },
|
{ label: __('Part Time'), value: 'Part Time' },
|
||||||
{ label: 'Contract', value: 'Contract' },
|
{ label: __('Contract'), value: 'Contract' },
|
||||||
{ label: 'Freelance', value: 'Freelance' },
|
{ label: __('Freelance'), value: 'Freelance' },
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const workModes = computed(() => {
|
const workModes = computed(() => {
|
||||||
return [
|
return [
|
||||||
{ label: 'On site', value: 'On-site' },
|
{ label: __('On site'), value: 'On-site' },
|
||||||
{ label: 'Hybrid', value: 'Hybrid' },
|
{ label: __('Hybrid'), value: 'Hybrid' },
|
||||||
{ label: 'Remote', value: 'Remote' },
|
{ label: __('Remote'), value: 'Remote' },
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const jobStatuses = computed(() => {
|
const jobStatuses = computed(() => {
|
||||||
return [
|
return [
|
||||||
{ label: 'Open', value: 'Open' },
|
{ label: __('Open'), value: 'Open' },
|
||||||
{ label: 'Closed', value: 'Closed' },
|
{ label: __('Closed'), value: 'Closed' },
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -302,8 +318,11 @@ const breadcrumbs = computed(() => {
|
|||||||
route: { name: 'Jobs' },
|
route: { name: 'Jobs' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: props.jobName == 'new' ? __('New Job') : __('Edit Job'),
|
label: props.jobName == 'new' ? __('New Job') : jobDetails.doc?.job_title,
|
||||||
route: { name: 'JobForm' },
|
route:
|
||||||
|
props.jobName == 'new'
|
||||||
|
? {}
|
||||||
|
: { name: 'JobDetail', params: { job: props.jobName } },
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
return crumbs
|
return crumbs
|
||||||
@@ -311,7 +330,7 @@ const breadcrumbs = computed(() => {
|
|||||||
|
|
||||||
usePageMeta(() => {
|
usePageMeta(() => {
|
||||||
return {
|
return {
|
||||||
title: props.jobName == 'new' ? __('New Job') : jobDetail.data?.job_title,
|
title: props.jobName == 'new' ? __('New Job') : jobDetails.doc?.job_title,
|
||||||
icon: brand.favicon,
|
icon: brand.favicon,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
:items="[{ label: __('Jobs'), route: { name: 'Jobs' } }]"
|
:items="[{ label: __('Jobs'), route: { name: 'Jobs' } }]"
|
||||||
/>
|
/>
|
||||||
<router-link
|
<router-link
|
||||||
v-if="user.data?.name"
|
v-if="
|
||||||
|
user.data?.name && settings.data?.allow_job_posting && !readOnlyMode
|
||||||
|
"
|
||||||
:to="{
|
:to="{
|
||||||
name: 'JobForm',
|
name: 'JobForm',
|
||||||
params: {
|
params: {
|
||||||
@@ -16,7 +18,7 @@
|
|||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Button v-if="!readOnlyMode" variant="solid">
|
<Button variant="solid">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<Plus class="h-4 w-4" />
|
<Plus class="h-4 w-4" />
|
||||||
</template>
|
</template>
|
||||||
@@ -123,7 +125,8 @@ import {
|
|||||||
usePageMeta,
|
usePageMeta,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { Plus, Search } from 'lucide-vue-next'
|
import { Plus, Search } from 'lucide-vue-next'
|
||||||
import { sessionStore } from '../stores/session'
|
import { sessionStore } from '@/stores/session'
|
||||||
|
import { useSettings } from '@/stores/settings'
|
||||||
import { inject, computed, ref, onMounted, watch } from 'vue'
|
import { inject, computed, ref, onMounted, watch } from 'vue'
|
||||||
import JobCard from '@/components/JobCard.vue'
|
import JobCard from '@/components/JobCard.vue'
|
||||||
import Link from '@/components/Controls/Link.vue'
|
import Link from '@/components/Controls/Link.vue'
|
||||||
@@ -133,6 +136,7 @@ const user = inject('$user')
|
|||||||
const jobType = ref(null)
|
const jobType = ref(null)
|
||||||
const workMode = ref(null)
|
const workMode = ref(null)
|
||||||
const { brand } = sessionStore()
|
const { brand } = sessionStore()
|
||||||
|
const { settings } = useSettings()
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
const country = ref(null)
|
const country = ref(null)
|
||||||
const filters = ref({})
|
const filters = ref({})
|
||||||
|
|||||||
@@ -130,7 +130,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"make_attachments_public": 1,
|
"make_attachments_public": 1,
|
||||||
"modified": "2025-12-02 16:58:49.903274",
|
"modified": "2026-02-19 14:26:14.027340",
|
||||||
"modified_by": "sayali@frappe.io",
|
"modified_by": "sayali@frappe.io",
|
||||||
"module": "Job",
|
"module": "Job",
|
||||||
"name": "Job Opportunity",
|
"name": "Job Opportunity",
|
||||||
@@ -149,24 +149,16 @@
|
|||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "LMS Student",
|
|
||||||
"select": 1,
|
|
||||||
"share": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 1,
|
"if_owner": 1,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "LMS Student",
|
"role": "LMS Student",
|
||||||
|
"select": 1,
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
// Copyright (c) 2022, Frappe and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on("Job Settings", {
|
|
||||||
// refresh: function(frm) {
|
|
||||||
// }
|
|
||||||
});
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"allow_rename": 1,
|
|
||||||
"creation": "2022-02-07 12:01:41.422955",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"allow_posting",
|
|
||||||
"title",
|
|
||||||
"subtitle"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "allow_posting",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Allow Job Posting From Website"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Job Board Title"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "subtitle",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Job Board Subtitle"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"index_web_pages_for_search": 1,
|
|
||||||
"issingle": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2022-02-11 15:56:38.958317",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Job",
|
|
||||||
"name": "Job Settings",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"role": "System Manager",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"states": []
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2022, Frappe and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class JobSettings(Document):
|
|
||||||
pass
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2022, Frappe and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class TestJobSettings(unittest.TestCase):
|
|
||||||
pass
|
|
||||||
+2
-1
@@ -118,4 +118,5 @@ lms.patches.v2_0.open_to_opportunities
|
|||||||
lms.patches.v2_0.open_to_work
|
lms.patches.v2_0.open_to_work
|
||||||
lms.patches.v2_0.share_enrollment
|
lms.patches.v2_0.share_enrollment
|
||||||
lms.patches.v2_0.give_user_list_permission #11-02-2026
|
lms.patches.v2_0.give_user_list_permission #11-02-2026
|
||||||
lms.patches.v2_0.rename_badge_assignment_event
|
lms.patches.v2_0.rename_badge_assignment_event
|
||||||
|
lms.patches.v2_0.enable_allow_job_posting
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.db.set_value("LMS Settings", None, "allow_job_posting", 1)
|
||||||
Reference in New Issue
Block a user