Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions education/education/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from frappe.model.mapper import get_mapped_doc
from frappe.utils import cstr, flt, getdate
from frappe.utils.dateutils import get_dates_from_timegrain
from datetime import datetime


def get_course(program):
Expand Down Expand Up @@ -759,3 +760,19 @@ def get_student_attendance(student, student_group):
filters={"student": student, "student_group": student_group, "docstatus": 1},
fields=["date", "status", "name"],
)


@frappe.whitelist()
def get_announcements():
announcements = frappe.get_all(
"Newsletter",
filters={"published": 1},
fields=["subject", "creation", "message"]
)

for announcement in announcements:
if "creation" in announcement:
announcement["creation"] = frappe.utils.pretty_date(announcement["creation"])

return announcements

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt

// frappe.ui.form.on("School Announcement", {
// refresh(frm) {

// },
// });
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:ANC-{MM}-{#####}",
"creation": "2025-02-26 16:22:04.198050",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"title",
"column_break_ywyl",
"posting_date",
"descriptions_section",
"description",
"section_break_uyky",
"announcement_date",
"column_break_uhyk",
"is_published"
],
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title"
},
{
"fieldname": "column_break_ywyl",
"fieldtype": "Column Break"
},
{
"default": "Today",
"fieldname": "posting_date",
"fieldtype": "Date",
"label": "Posting Date"
},
{
"default": "0",
"fieldname": "is_published",
"fieldtype": "Check",
"label": "Is Published?"
},
{
"fieldname": "descriptions_section",
"fieldtype": "Section Break",
"label": "Descriptions"
},
{
"fieldname": "description",
"fieldtype": "Text Editor",
"label": "Description"
},
{
"fieldname": "section_break_uyky",
"fieldtype": "Section Break"
},
{
"fieldname": "announcement_date",
"fieldtype": "Date",
"label": "Announcement Date"
},
{
"fieldname": "column_break_uhyk",
"fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-02-26 16:33:07.237999",
"modified_by": "Administrator",
"module": "Education",
"name": "School Announcement",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document


class SchoolAnnouncement(Document):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt

# import frappe
from frappe.tests.utils import FrappeTestCase


class TestSchoolAnnouncement(FrappeTestCase):
pass
6 changes: 3 additions & 3 deletions education/public/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
<link rel="icon" href="/assets/education/frontend/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Frappe Education</title>
<script type="module" crossorigin src="/assets/education/frontend/assets/index.5fb23331.js"></script>
<script type="module" crossorigin src="/assets/education/frontend/assets/index.f6f5f244.js"></script>
<link rel="modulepreload" href="/assets/education/frontend/assets/frappe-ui.cf491ab7.js">
<link rel="stylesheet" href="/assets/education/frontend/assets/frappe-ui.005832b0.css">
<link rel="stylesheet" href="/assets/education/frontend/assets/index.570170c2.css">
<link rel="stylesheet" href="/assets/education/frontend/assets/index.b142f333.css">
</head>
<body>
<div id="app"></div>
Expand All @@ -26,6 +26,6 @@
}
link.href = '{{ logo }}'
</script>

</body>
</html>
2 changes: 1 addition & 1 deletion education/public/node_modules
6 changes: 6 additions & 0 deletions frontend/src/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ const links = [
to: '/attendance',
icon: UserCheck,
},
{
label: 'Announcement',
to: '/announcements',
icon: UserCheck,
},

// {
// // TODO: create School Diary Page with card like CRM and from ListView go to Resource Document of each Card
// label: 'Notes',
Expand Down
104 changes: 104 additions & 0 deletions frontend/src/pages/Announcement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<template>
<div class="">
<div v-if="tableData.rows.length > 0" class="px-5 py-4">
<ListView
:columns="tableData.columns"
:rows="tableData.rows"
:options="{
selectable: false,
showTooltip: false,
onRowClick: (row) => openAnnouncement(row),
}"
row-key="name"
>
<ListHeader>
<ListHeaderItem
v-for="column in tableData.columns"
:key="column.key"
:item="column"
/>
</ListHeader>
<ListRow
v-for="row in tableData.rows"
:key="row.name"
:row="row"
v-slot="{ column, item }"
>
<ListRowItem :item="item" :align="column.align">
<template v-if="column.key === 'subject'">
<span class="font-normal">{{ item }}</span>
</template>
<template v-else-if="column.key === 'creation'">
<span class="text-gray-600"> {{ item }}</span>
</template>
</ListRowItem>
</ListRow>
</ListView>
</div>

<div v-else>
<MissingData message="No announcements available" />
</div>

<Dialog
v-model="showDialog"
:options="{
title: selectedAnnouncement.subject,
size: '2xl',
}"
>
<template #body-content>
<div class="ql-editor read-mode" v-html="selectedAnnouncement.message"></div>
</template>
</Dialog>
</div>
</template>

<script setup>
import { reactive, ref } from 'vue'
import {
ListView,
ListHeader,
ListHeaderItem,
ListRow,
ListRowItem,
Dialog,
createResource,
} from 'frappe-ui'
import MissingData from '@/components/MissingData.vue'

const tableData = reactive({
rows: [],
columns: [
{
label: 'Subject',
key: 'subject',
width: 2,
},
{
label: 'Posting Date',
key: 'creation',
width: 1,
},
],
})

const showDialog = ref(false)
const selectedAnnouncement = ref({})

const fetchAnnouncements = createResource({
url: 'education.education.api.get_announcements',
onSuccess: (data) => {
tableData.rows = data
},
onError: (err) => {
console.error('Error fetching announcements:', err)
},
auto: true,
})

const openAnnouncement = (announcement) => {
selectedAnnouncement.value = announcement
showDialog.value = true
}
</script>
5 changes: 5 additions & 0 deletions frontend/src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const routes = [
name: 'Attendance',
component: () => import('@/pages/Attendance.vue'),
},
{
path: '/announcements',
name: 'Announcements',
component: () => import('@/pages/Announcement.vue'),
},
{
path: '/:catchAll(.*)',
redirect: '/schedule',
Expand Down
2 changes: 1 addition & 1 deletion node_modules/.yarn-integrity

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.