diff --git a/application/controllers/api/frontend/v1/Bookmark.php b/application/controllers/api/frontend/v1/Bookmark.php
new file mode 100644
index 000000000..a811843ce
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Bookmark.php
@@ -0,0 +1,109 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+class Bookmark extends FHCAPI_Controller
+{
+
+ /**
+ * Object initialization
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getBookmarks' => self::PERM_LOGGED,
+ 'delete' => self::PERM_LOGGED,
+ 'insert' => self::PERM_LOGGED,
+ ]);
+
+ $this->load->model('dashboard/Bookmark_model', 'BookmarkModel');
+
+ $this->uid = getAuthUID();
+ $this->pid = getAuthPersonID();
+
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+
+ /**
+ * gets the bookmarks associated to a user
+ * @access public
+ * @return void
+ */
+ public function getBookmarks()
+ {
+ $bookmarks = $this->BookmarkModel->loadWhere(["uid"=>$this->uid]);
+
+ $bookmarks = $this->getDataOrTerminateWithError($bookmarks);
+
+ $this->terminateWithSuccess($bookmarks);
+ }
+
+ /**
+ * deletes bookmark from associated user
+ * @access public
+ * @return void
+ */
+ public function delete($bookmark_id)
+ {
+ $bookmark = $this->BookmarkModel->load($bookmark_id);
+
+ $bookmark = current($this->getDataOrTerminateWithError($bookmark));
+
+ // only delete bookmark if the user is the owner of the bookmark
+ if($bookmark->uid == $this->uid || $this->permissionlib->isBerechtigt('admin')){
+
+ $delete_result = $this->BookmarkModel->delete($bookmark_id);
+
+ $delete_result = $this->getDataOrTerminateWithError($delete_result);
+
+ $this->terminateWithSuccess($delete_result);
+ }else{
+ $this->_outputAuthError(['delete' => ['admin:rw']]);
+ }
+ }
+
+ /**
+ * inserts new bookmark into the bookmark table
+ * @access public
+ * @return void
+ */
+ public function insert()
+ {
+ // form validation
+ $this->load->library('form_validation');
+ $this->form_validation->set_rules('url', 'URL', 'required|valid_url|max_length[511]');
+ $this->form_validation->set_rules('title', 'Title', 'required|max_length[255]');
+ if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $url = $this->input->post('url',true);
+ $title = $this->input->post('title',true);
+ $tag = $this->input->post('tag', true);
+
+ $insert_into_result = $this->BookmarkModel->insert(['uid'=>$this->uid, 'url'=>$url, 'title'=>$title,'tag'=>$tag, 'insertvon'=>$this->uid, 'updateamum'=>NULL, 'updatevon'=>NULL]);
+
+ $insert_into_result = $this->getDataOrTerminateWithError($insert_into_result);
+
+ $this->terminateWithSuccess($insert_into_result);
+
+ }
+}
+
diff --git a/application/models/dashboard/Bookmark_model.php b/application/models/dashboard/Bookmark_model.php
new file mode 100644
index 000000000..5efacc26b
--- /dev/null
+++ b/application/models/dashboard/Bookmark_model.php
@@ -0,0 +1,18 @@
+dbTable = 'dashboard.tbl_bookmark';
+ $this->pk = 'bookmark_id';
+ }
+
+
+
+
+}
diff --git a/public/js/api/bookmark.js b/public/js/api/bookmark.js
new file mode 100644
index 000000000..30e49d50d
--- /dev/null
+++ b/public/js/api/bookmark.js
@@ -0,0 +1,27 @@
+export default {
+
+ getBookmarks: function () {
+ return this.$fhcApi.get(
+ `/api/frontend/v1/Bookmark/getBookmarks`
+ ,{}
+ );
+ },
+
+ delete: function (bookmark_id) {
+ return this.$fhcApi.get(
+ `/api/frontend/v1/Bookmark/delete/${bookmark_id}`
+ ,{}
+ );
+ },
+
+ insert: function ({url, title, tag}) {
+ return this.$fhcApi.post(
+ `/api/frontend/v1/Bookmark/insert`
+ ,{
+ url: url,
+ title: title,
+ tag: tag
+ }
+ );
+ },
+}
\ No newline at end of file
diff --git a/public/js/api/fhcapifactory.js b/public/js/api/fhcapifactory.js
index 73ce0dd7f..99f154992 100644
--- a/public/js/api/fhcapifactory.js
+++ b/public/js/api/fhcapifactory.js
@@ -22,6 +22,7 @@ import filter from "./filter.js";
import studstatus from "./studstatus.js";
import profil from "./profil.js";
import profilUpdate from "./profilUpdate.js";
+import bookmark from "./bookmark.js";
export default {
search,
@@ -31,4 +32,5 @@ export default {
studstatus,
profil,
profilUpdate,
+ bookmark,
};
diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js
index ebcbb4b78..a20bb5b64 100755
--- a/public/js/apps/Dashboard/Fhc.js
+++ b/public/js/apps/Dashboard/Fhc.js
@@ -1,4 +1,5 @@
import FhcDashboard from '../../components/Dashboard/Dashboard.js';
+import Phrasen from "../../plugin/Phrasen.js";
const app = Vue.createApp({
data: () => ({
@@ -9,4 +10,5 @@ const app = Vue.createApp({
}
});
app.config.unwrapInjectedRef = true;
+app.use(Phrasen);
app.mount('#content');
diff --git a/public/js/components/Dashboard/Item.js b/public/js/components/Dashboard/Item.js
index 43e03ebc7..484171857 100755
--- a/public/js/components/Dashboard/Item.js
+++ b/public/js/components/Dashboard/Item.js
@@ -3,22 +3,23 @@ import CachedWidgetLoader from "../../composables/Dashboard/CachedWidgetLoader.j
export default {
components: {
- BsModal
+ BsModal,
},
data: () => ({
- component: '',
+ component: "",
arguments: null,
target: false,
widget: null,
tmpConfig: {},
isLoading: false,
- hasConfig: true
+ hasConfig: true,
+ sharedData: null,
}),
emits: [
"change",
"remove",
"dragstart",
- "resizestart",
+ "resizestart"
],
props: [
"id",
@@ -28,17 +29,16 @@ export default {
"custom",
"hidden",
"editMode",
- "loading"
+ "loading",
],
computed: {
isResizeable() {
- if (!this.widget)
- return false;
+ if (!this.widget) return false;
return this.widget.setup.width.max || this.widget.setup.height.max;
},
ready() {
- return this.component && this.arguments !== null
- }
+ return this.component && this.arguments !== null;
+ },
},
methods: {
mouseDown(e) {
@@ -46,18 +46,19 @@ export default {
},
startDrag(e) {
if (this.$refs.dragHandle.contains(this.target)) {
- this.$emit('dragstart', e);
- } else if (this.isResizeable && this.$refs.resizeHandle.contains(this.target)) {
- if (this.isResizeable)
- this.$emit('resizestart', e);
- else
- e.preventDefault();
+ this.$emit("dragstart", e);
+ } else if (
+ this.isResizeable &&
+ this.$refs.resizeHandle.contains(this.target)
+ ) {
+ if (this.isResizeable) this.$emit("resizestart", e);
+ else e.preventDefault();
} else {
e.preventDefault();
}
},
openConfig() {
- this.tmpConfig = {...this.arguments};
+ this.tmpConfig = { ...this.arguments };
this.$refs.config.show();
},
setConfig(hasConfig) {
@@ -65,39 +66,39 @@ export default {
},
changeConfig() {
this.isLoading = true;
- let config = {...this.tmpConfig};
+ let config = { ...this.tmpConfig };
this.sendChangeConfig(config);
},
changeConfigManually() {
- let config = {...this.arguments};
+ let config = { ...this.arguments };
this.sendChangeConfig(config);
},
sendChangeConfig(config) {
for (var k in config) {
if (this.widget.arguments[k] == config[k]) {
- delete config[k];
+ delete config[k];
}
}
- this.$emit('change', config);
- }
+ this.$emit("change", config);
+ },
},
watch: {
config() {
- this.arguments = {...this.widget.arguments, ...this.config};
- this.tmpConfig = {...this.arguments};
+ this.arguments = { ...this.widget.arguments, ...this.config };
+ this.tmpConfig = { ...this.arguments };
this.$refs.config.hide();
this.isLoading = false;
- }
+ },
},
async created() {
this.widget = await CachedWidgetLoader.loadWidget(this.id);
- let component = (await import('../' + this.widget.setup.file)).default;
- this.$options.components['widget' + this.widget.widget_id] = component;
- this.component = 'widget' + this.widget.widget_id;
- this.arguments = {...this.widget.arguments, ...this.config};
- this.tmpConfig = {...this.arguments};
+ let component = (await import("../" + this.widget.setup.file)).default;
+ this.$options.components["widget" + this.widget.widget_id] = component;
+ this.component = "widget" + this.widget.widget_id;
+ this.arguments = { ...this.widget.arguments, ...this.config };
+ this.tmpConfig = { ...this.arguments };
},
- template: `
+ template: /*html*/ `
@@ -116,7 +117,7 @@ export default {
-
+
@@ -124,10 +125,10 @@ export default {
{{ widget ? 'Config for ' + widget.setup.name : '' }}
-
+
-
+
@@ -135,5 +136,5 @@ export default {
- `
-}
\ No newline at end of file
+ `,
+};
diff --git a/public/js/components/DashboardWidget/Abstract.js b/public/js/components/DashboardWidget/Abstract.js
index a21c9834f..25c5cfb9c 100755
--- a/public/js/components/DashboardWidget/Abstract.js
+++ b/public/js/components/DashboardWidget/Abstract.js
@@ -3,17 +3,27 @@ export default {
"config",
"width",
"height",
- "configMode"
+ "configMode",
+ "sharedData"
],
emits: [
"setConfig",
- "change" // TODO(chris): do we need this?
+ "change", // TODO(chris): do we need this?
+ "update:sharedData"
],
computed: {
apiurl() {
const app_root = FHC_JS_DATA_STORAGE_OBJECT.app_root;
const ci_router = FHC_JS_DATA_STORAGE_OBJECT.ci_router;
return app_root + ci_router;
+ },
+ shared: {
+ get() {
+ return this.sharedData;
+ },
+ set(value) {
+ this.$emit('update:sharedData', value);
+ }
}
},
methods: {
diff --git a/public/js/components/DashboardWidget/Url.js b/public/js/components/DashboardWidget/Url.js
index f374b7ed8..eb7dfdae4 100755
--- a/public/js/components/DashboardWidget/Url.js
+++ b/public/js/components/DashboardWidget/Url.js
@@ -1,84 +1,123 @@
import AbstractWidget from './Abstract';
export default {
- name: 'WidgetsUrl',
- data: () => ({
- links: []
- }),
- mixins: [
- AbstractWidget
- ],
- computed: {
- tagName() {
- return this.config.tag !== undefined && this.config.tag.length > 0 ? this.config.tag : 'Meine Urls';
- }
+ name: "WidgetsUrl",
+ data: () => ({
+ title_input: "",
+ url_input: "",
+ }),
+ mixins: [AbstractWidget],
+ computed: {
+ tagName() {
+ return this.config.tag !== undefined && this.config.tag.length > 0
+ ? this.config.tag
+ : this.$p.t("bookmark", "myBookmarks");
},
- methods: {
- addLink(){
- let linkId = this.links.length;
+ emptyBookmarks() {
+ if (this.shared instanceof Array && this.shared.length == 0) return true;
- this.links.push({
- id: linkId,
- tag: this.config.tag,
- title: this.title,
- url: this.url
- })
- },
- removeLink(linkId){
- let indexToRemove = this.links.findIndex((obj => obj.id === linkId));
- this.links.splice(indexToRemove, 1);
- }
+ if (!this.shared) return true;
+
+ return false;
},
- created() {
- this.links = TEST_LINKS;
- // this.links = TEST_KEINE_LINKS;
+ },
+ methods: {
+ async fetchBookmarks() {
+ await this.$fhcApi.factory.bookmark
+ .getBookmarks()
+ .then((res) => res.data)
+ .then((result) => {
+ this.shared = result;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
},
- template: `
+ async confirmDelete() {
+ if ((await this.$fhcAlert.confirmDelete()) === false) return;
+ },
+ addLink() {
+ this.$fhcApi.factory.bookmark
+ .insert({
+ tag: this.config.tag,
+ title: this.title_input,
+ url: this.url_input,
+ })
+ .then((res) => res.data)
+ .then((result) => {
+ this.$fhcAlert.alertInfo(this.$p.t("bookmark", "bookmarkAdded"));
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+
+ // reset the values for the title and url inputs
+ this.title_input = "";
+ this.url_input = "";
+
+ // refetch the bookmarks to see the updates
+ this.fetchBookmarks();
+ },
+ async removeLink(bookmark_id) {
+ await this.confirmDelete();
+ this.$fhcApi.factory.bookmark
+ .delete(bookmark_id)
+ .then((res) => res.data)
+ .then((result) => {
+ this.$fhcAlert.alertInfo(this.$p.t("bookmark", "bookmarkDeleted"));
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+
+ // refetch the bookmarks to see the updates
+ this.fetchBookmarks();
+ },
+ },
+ async mounted() {
+ await this.fetchBookmarks();
+ },
+ template: /*html*/ `
`
+ `,
+};
+
+/*
+Link JSON structure:
+{
+ "bookmark_id": number,
+ "uid": string,
+ "url": string,
+ "title": string,
+ "tag": string,
+ "insertamum": "2024-07-30 14:33:03.699318",
+ "insertvon": null,
+ "updateamum": null,
+ "updatevon": null
}
-const TEST_KEINE_LINKS = [];
-const TEST_LINKS = [
- {
- id: 0,
- tag: 'Zeitverwaltung',
- title: 'Zeitverwaltung' + 'link 0',
- url: 'https://www.technikum-wien.at'
- },
- {
- id: 1,
- tag: 'Zeitverwaltung',
- title: 'Zeitverwaltung' + 'link 1',
- url: 'https://www.technikum-wien.at'
- },
- {
- id: 2,
- tag: 'Zeitverwaltung',
- title: 'Zeitverwaltung' + 'link 2',
- url: 'https://www.technikum-wien.at'
- },
- {
- id: 3,
- tag: 'Zeitverwaltung',
- title: 'Zeitverwaltung' + 'link 3',
- url: 'https://www.technikum-wien.at'
- }
-];
\ No newline at end of file
+*/
diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php
index b3c070095..17487b5d3 100755
--- a/system/dbupdate_3.4.php
+++ b/system/dbupdate_3.4.php
@@ -58,6 +58,7 @@ require_once('dbupdate_3.4/25999_cis4_cms.php');
require_once('dbupdate_3.4/36530_bis_internationsalisierung_codextabelle_neuerungen.php');
require_once('dbupdate_3.4/34543_ux_template.php');
require_once('dbupdate_3.4/17513_Entwicklungsteam.php');
+require_once('dbupdate_3.4/41134_bookmark_dashboardWidget.php');
@@ -410,6 +411,8 @@ $tabellen=array(
"wawi.tbl_rechnungsbetrag" => array("rechnungsbetrag_id","rechnung_id","mwst","betrag","bezeichnung","ext_id"),
"wawi.tbl_aufteilung" => array("aufteilung_id","bestellung_id","oe_kurzbz","anteil","insertamum","insertvon","updateamum","updatevon"),
"wawi.tbl_aufteilung_default" => array("aufteilung_id","kostenstelle_id","oe_kurzbz","anteil","insertamum","insertvon","updateamum","updatevon"),
+ "dashboard.tbl_bookmark" => array("bookmark_id","uid","url","title","tag","insertamum","insertvon","updateamum","updatevon"),
+
);
$tabs=array_keys($tabellen);
diff --git a/system/dbupdate_3.4/41134_bookmark_dashboardWidget.php b/system/dbupdate_3.4/41134_bookmark_dashboardWidget.php
new file mode 100644
index 000000000..ebcdeba91
--- /dev/null
+++ b/system/dbupdate_3.4/41134_bookmark_dashboardWidget.php
@@ -0,0 +1,44 @@
+db_query("SELECT to_regclass('dashboard.tbl_bookmark')"))
+{
+ $qry = "BEGIN TRANSACTION;
+
+ CREATE TABLE IF NOT EXISTS dashboard.tbl_bookmark(
+ bookmark_id BIGINT PRIMARY KEY,
+ uid VARCHAR(255) NOT NULL,
+ url VARCHAR(511) NOT NULL,
+ title VARCHAR(255) NOT NULL,
+ tag VARCHAR(255) NULL,
+ insertamum TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
+ insertvon VARCHAR(255) NULL REFERENCES public.tbl_benutzer(uid),
+ updateamum TIMESTAMP NULL,
+ updatevon VARCHAR(255) NULL REFERENCES public.tbl_benutzer(uid)
+ );
+
+ ALTER TABLE dashboard.tbl_bookmark ADD CONSTRAINT tbl_bookmark_fk FOREIGN KEY(uid) REFERENCES public.tbl_benutzer(uid);
+
+ CREATE SEQUENCE IF NOT EXISTS dashboard.tbl_bookmark_sequence
+ AS BIGINT
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ START WITH 1
+ CACHE 1
+ OWNED BY dashboard.tbl_bookmark.bookmark_id;
+
+ ALTER TABLE dashboard.tbl_bookmark ALTER COLUMN bookmark_id SET DEFAULT nextval('dashboard.tbl_bookmark_sequence ');
+
+ GRANT SELECT, INSERT, UPDATE, DELETE ON dashboard.tbl_bookmark TO vilesci;
+ GRANT SELECT, INSERT, UPDATE, DELETE ON dashboard.tbl_bookmark TO web;
+ GRANT SELECT, UPDATE ON dashboard.tbl_bookmark_sequence TO vilesci;
+ GRANT SELECT, UPDATE ON dashboard.tbl_bookmark_sequence TO web;
+
+ COMMIT TRANSACTION;";
+
+ if (!$db->db_query($qry))
+ echo 'error occurred during tbl_bookmark creation: ' . $db->db_last_error() . '
';
+ else
+ echo '
dashboard.tbl_bookmark and dashboard.tbl_bookmark_sequence was created';
+
+}
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php
index 8dc1d163f..49a3a0bdc 100755
--- a/system/phrasesupdate.php
+++ b/system/phrasesupdate.php
@@ -27489,7 +27489,130 @@ array(
'insertvon' => 'system'
)
)
- )
+ ),
+ // BOOKMARK PHRASEN ----------------------------------------------------------------------
+ array(
+ 'app' => 'core',
+ 'category' => 'bookmark',
+ 'phrase' => 'newLink',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Neuer Link',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'New Link',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'bookmark',
+ 'phrase' => 'saveLink',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Link speichern',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Save link',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'bookmark',
+ 'phrase' => 'bookmarkDeleted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Link gelöscht',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Link deleted',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'bookmark',
+ 'phrase' => 'bookmarkAdded',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Link hinzugefügt',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Link added',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'bookmark',
+ 'phrase' => 'myBookmarks',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Meine Urls',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'My Urls',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'bookmark',
+ 'phrase' => 'emptyBookmarks',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Du hast noch keine Bookmarks gesetzt',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'You have not set any bookmarks yet',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+
+
);