summaryrefslogtreecommitdiff
path: root/src/web
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-05-20 17:11:38 -0400
committerFreya Murphy <freya@freyacat.org>2024-05-20 17:11:38 -0400
commit708594d32ffe779cf547c816fa7cdd19d095be2e (patch)
tree30d28553316db02bc027664e17b76d58f2e352ff /src/web
parentadd en_CAT makefile and use ucfirst/ucwords (diff)
downloadxssbook2-708594d32ffe779cf547c816fa7cdd19d095be2e.tar.gz
xssbook2-708594d32ffe779cf547c816fa7cdd19d095be2e.tar.bz2
xssbook2-708594d32ffe779cf547c816fa7cdd19d095be2e.zip
v2 done
Diffstat (limited to 'src/web')
-rw-r--r--src/web/_controller/apps/settings.php41
-rw-r--r--src/web/_controller/modal.php4
-rw-r--r--src/web/_controller/template.php3
-rw-r--r--src/web/_model/apps/settings.php16
-rw-r--r--src/web/_views/apps/profile/main.php2
-rw-r--r--src/web/_views/apps/settings/main.php151
-rw-r--r--src/web/_views/footer.php2
-rw-r--r--src/web/_views/header.php17
-rw-r--r--src/web/_views/modal/about.php28
-rw-r--r--src/web/_views/template/toast.php2
-rw-r--r--src/web/config/aesthetic.php5
-rw-r--r--src/web/config/routes.php1
-rw-r--r--src/web/helper/image.php43
-rw-r--r--src/web/lang/en_US/apps/settings.php17
-rw-r--r--src/web/lang/en_US/common_lang.php9
15 files changed, 332 insertions, 9 deletions
diff --git a/src/web/_controller/apps/settings.php b/src/web/_controller/apps/settings.php
new file mode 100644
index 0000000..8a409cc
--- /dev/null
+++ b/src/web/_controller/apps/settings.php
@@ -0,0 +1,41 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Settings_controller extends Controller {
+
+ // the home model
+ private $settings_model;
+
+ // the format model
+ protected $format_model;
+
+ // the post controller
+ protected $post_controller;
+
+ // the people controller
+ protected $people_controller;
+
+ function __construct($load) {
+ parent::__construct($load);
+ $this->settings_model = $this->load->model('apps/settings');
+ }
+
+ public function index(): void {
+ if (!$this->main->session) {
+ $this->redirect('/auth/login');
+ }
+
+ parent::index();
+ $data = $this->settings_model->get_data();
+
+ if (!$data) {
+ $this->error(404);
+ }
+
+ $this->load->app_lang($this->main->info['lang'], 'auth');
+ $this->view('header', $data);
+ $this->view('apps/settings/main', $data);
+ $this->view('footer', $data);
+ }
+
+}
+
+?>
diff --git a/src/web/_controller/modal.php b/src/web/_controller/modal.php
index 40a2b42..da17cca 100644
--- a/src/web/_controller/modal.php
+++ b/src/web/_controller/modal.php
@@ -21,6 +21,10 @@ class Modal_controller extends Controller {
$this->modal('new_post');
}
+ public function about(): void {
+ $this->modal('about');
+ }
+
public function register(): void {
$this->load->app_lang(
$this->main->info['lang'],
diff --git a/src/web/_controller/template.php b/src/web/_controller/template.php
index 7a8cdf8..879eadc 100644
--- a/src/web/_controller/template.php
+++ b/src/web/_controller/template.php
@@ -13,7 +13,8 @@ class Template_controller extends Controller {
$data = array(
'msg' => $this->request_model->get_str('msg', FALSE),
'detail' => $this->request_model->get_str('detail', FALSE),
- 'hint' => $this->request_model->get_str('hint', FALSE)
+ 'hint' => $this->request_model->get_str('hint', FALSE),
+ 'type' => $this->request_model->get_str('type', 'error')
);
$this->view('template/toast', $data);
}
diff --git a/src/web/_model/apps/settings.php b/src/web/_model/apps/settings.php
new file mode 100644
index 0000000..1f1e3f9
--- /dev/null
+++ b/src/web/_model/apps/settings.php
@@ -0,0 +1,16 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Settings_model extends Model {
+
+ private $request_model;
+
+ function __construct($load) {
+ parent::__construct($load);
+ $this->request_model = $this->load->model('request');
+ }
+
+ public function get_data(): ?array {
+ $data = parent::get_data();
+ $data['title'] = ucfirst(lang('title'));
+ return $data;
+ }
+}
diff --git a/src/web/_views/apps/profile/main.php b/src/web/_views/apps/profile/main.php
index 919b190..21b3b46 100644
--- a/src/web/_views/apps/profile/main.php
+++ b/src/web/_views/apps/profile/main.php
@@ -3,7 +3,7 @@
<div id="main-content">
<div id="profile-header-container">
<div id="profile-header" class="col">
- <?=image('/api/rpc/profile_banner?user_id=' . $user['id'], 'banner')?>
+ <?=image('/api/rpc/profile_banner?user_id=' . $user['id'], 'banner', mime: $user['banner_mime'])?>
<div class="info row">
<div class="pfp-wrapper">
<?=pfp($user)?>
diff --git a/src/web/_views/apps/settings/main.php b/src/web/_views/apps/settings/main.php
new file mode 100644
index 0000000..0cdc4f2
--- /dev/null
+++ b/src/web/_views/apps/settings/main.php
@@ -0,0 +1,151 @@
+<?php /* Copyright (c) 2024 Freya Murphy */ ?>
+<?php /* vi: syntax=php */ ?>
+
+<?php
+
+$user = $this->main->user();
+
+function __create_form($user, $col) {
+ $ph = ucfirst(lang('ph_' . $col));
+ $val = $user[$col];
+ return "<form action=\"\" class=\"row mt settings-form\" onsubmit=\"handleSubmit(event)\">
+ <div class=\"rel mb\" style=\"flex: 1\">
+ <input
+ type=\"text\"
+ name=\"{$col}\"
+ id=\"{$col}\"
+ placeholder=\" \"
+ value=\"{$val}\"
+ >
+ <label for=\"{$col}\">
+ {$ph}
+ </label>
+ </div>
+ <input type=\"hidden\" name=\"col\" value=\"{$col}\">
+ <input type=\"hidden\" name=\"uid\" value=\"{$user['id']}\">
+ <button
+ class=\"btn btn-submit ml\"
+ style=\"flex: 0; height: fit-content;\"
+ ><i class=\"mi\">check</i></button>
+ </form>";
+}
+
+?>
+
+<script>
+
+function onSuccess() {
+ successToast(<?=json_encode(ucfirst(lang('settings_success')))?>);
+}
+
+function handleSubmit(e) {
+ e.preventDefault();
+ let el = e.target.elements;
+ let col = el.col.value;
+ let uid = el.uid.value;
+ let val = el[col].value;
+
+ $.ajax({
+ url: '/api/user?id=eq.' + uid,
+ method: 'PATCH',
+ data: JSON.stringify({ [col]: val }),
+ success: onSuccess
+ });
+
+}
+
+const toBase64 = file => new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = () => resolve(reader.result);
+ reader.onerror = reject;
+});
+
+function updateMedia(media_type) {
+
+ var input = document.createElement('input');
+ input.type = 'file';
+
+ input.onchange = async (e) => {
+ var file = e.target.files[0];
+ var data = (await toBase64(file)).split(";");
+ var mime = data[0].split(":")[1];
+ var content = data[1].split(",")[1];
+
+ $.ajax({
+ url: '/api/rpc/update_user_media',
+ method: 'POST',
+ data: JSON.stringify({
+ media_type, mime, content
+ }),
+ success: onSuccess
+ });
+
+ }
+
+ input.click();
+
+}
+
+function resetMedia(media_type) {
+ $.ajax({
+ url: '/api/rpc/delete_user_media',
+ method: 'POST',
+ data: JSON.stringify({
+ media_type
+ }),
+ success: onSuccess
+ });
+}
+</script>
+
+<div id="main-content">
+ <div id="settings" class="card">
+ <h1><?=ucfirst(lang('title'))?></h1>
+ <hr class="mt">
+ <h2><?=ucfirst(lang('general_title'))?></h2>
+ <strong><?=ucfirst(lang('general_desc'))?></strong>
+ <?=__create_form($user, 'username')?>
+ <?=__create_form($user, 'email')?>
+ <?=__create_form($user, 'first_name')?>
+ <?=__create_form($user, 'last_name')?>
+ <?=__create_form($user, 'gender')?>
+ <hr class="mt">
+ <h2><?=ucfirst(lang('media_title'))?></h2>
+ <strong><?=ucfirst(lang('media_desc'))?></strong>
+ <h3><?=ucfirst(lang('ph_avatar'))?></h3>
+ <div class="row">
+ <?=image(
+ "/api/rpc/profile_avatar?user_id={$user['id']}",
+ height: '100px'
+ )?>
+ <div class="col ml">
+ <button
+ class="btn btn-alt btn-blue"
+ onclick="updateMedia('avatar')"
+ ><?=ucfirst(lang('update'))?></button>
+ <button
+ class="btn btn-alt btn-blue mt"
+ onclick="resetMedia('avatar')"
+ ><?=ucfirst(lang('reset'))?></button>
+ </div>
+ </div>
+ <h3><?=ucfirst(lang('ph_banner'))?></h3>
+ <div class="row">
+ <?=image(
+ "/api/rpc/profile_banner?user_id={$user['id']}",
+ height: '100px'
+ )?>
+ <div class="col ml">
+ <button
+ class="btn btn-alt btn-blue"
+ onclick="updateMedia('banner')"
+ ><?=ucfirst(lang('update'))?></button>
+ <button
+ class="btn btn-alt btn-blue mt"
+ onclick="resetMedia('banner')"
+ ><?=ucfirst(lang('reset'))?></button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/src/web/_views/footer.php b/src/web/_views/footer.php
index 9040c3a..bc9b3a2 100644
--- a/src/web/_views/footer.php
+++ b/src/web/_views/footer.php
@@ -1,7 +1,7 @@
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
<?php /* vi: syntax=php */ ?>
<footer>
- Freya Murphy © 2023 | <a href="https://freya.cat">freya.cat</a>
+ <?=ucfirst(lang('copyright'))?> | <a href="https://freya.cat">freya.cat</a>
</footer>
<body>
diff --git a/src/web/_views/header.php b/src/web/_views/header.php
index 97eb435..98fcf81 100644
--- a/src/web/_views/header.php
+++ b/src/web/_views/header.php
@@ -55,7 +55,7 @@
</script>
<?=pfp($self, FALSE, 'toggleUserMenu()')?>
<div class="card col hidden" id="user-menu">
- <span class="row" id="user-menu-header">
+ <span class="row mr" id="user-menu-header">
<?=pfp($self, FALSE)?>
<span class="col">
<strong><?=$this->format_model->name($self)?></strong>
@@ -65,16 +65,25 @@
<hr>
<?=ilang(
'action_profile',
+ id: 'action-profile',
class: 'btn',
href: '/profile?id=' . $self['id']
)?>
<?=ilang(
+ 'action_xssbook_about',
+ id: 'action-xssbook-about',
+ class: 'btn',
+ click: 'viewAbout'
+ )?>
+ <?=ilang(
'action_settings',
+ id: 'action-settings',
class: 'btn',
href: '/settings'
)?>
<?=ilang(
'action_logout',
+ id: 'action-logout',
class: 'btn',
href: '/auth/logout'
)?>
@@ -84,6 +93,11 @@
<?php endif; ?>
</div>
<script>
+ $('#action-xssbook-about').on('click', function() {
+ $.get( "/modal/about", function (data) {
+ $(document.body).append(data);
+ });
+ })
$('#action-hamburger').on('click', function() {
let menu = $('.nav-center');
menu.toggleClass('visible');
@@ -94,7 +108,6 @@
userMenu = $('#user-menu');
var nav = $('.nav');
document.onclick = function(event) {
- console.log(event.target, nav[0]);
let outside = !(nav[0].contains(event.target));
if (outside) {
userMenu.addClass('hidden');
diff --git a/src/web/_views/modal/about.php b/src/web/_views/modal/about.php
new file mode 100644
index 0000000..746607e
--- /dev/null
+++ b/src/web/_views/modal/about.php
@@ -0,0 +1,28 @@
+<?php /* Copyright (c) 2024 Freya Murphy */ ?>
+<?php /* vi: syntax=php */ ?>
+<div id="about-modal-body">
+ <span class="logo">xssbook</span>
+ <hr>
+ <span class="mb"><?=ucfirst(lang('version'))?></span>
+ <span><?=ucfirst(lang('copyright'))?></span>
+ <hr>
+ <a class="btn btn-blue" href="https://g.freya.cat/freya/xssbook2">Source Code</a>
+</div>
+<style>
+#about-modal-body {
+ display: flex;
+ margin-top: 50px;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ font-weight: bold;
+ font-size: 1.1rem;
+ padding: 1rem;
+}
+#about-modal-body .logo {
+ color: var(--blue);
+ font-family: facebook;
+ font-size: 2.25rem;
+ margin-bottom: 1rem;
+}
+</style>
diff --git a/src/web/_views/template/toast.php b/src/web/_views/template/toast.php
index ae2e7d8..0a6a82f 100644
--- a/src/web/_views/template/toast.php
+++ b/src/web/_views/template/toast.php
@@ -20,7 +20,7 @@
}
?>
-<div class="toast error">
+<div class="toast <?=$type?>">
<?=$lang_msg?>
<?=ilang('action_close', class: 'action-close-toast')?>
</div>
diff --git a/src/web/config/aesthetic.php b/src/web/config/aesthetic.php
index d37f4a9..5a66660 100644
--- a/src/web/config/aesthetic.php
+++ b/src/web/config/aesthetic.php
@@ -49,6 +49,11 @@ class Aesthetic {
'css/post.css'
],
),
+ 'settings' => array(
+ 'css' => [
+ 'css/settings.css'
+ ]
+ ),
);
}
/**
diff --git a/src/web/config/routes.php b/src/web/config/routes.php
index 1275bfe..a2a71c0 100644
--- a/src/web/config/routes.php
+++ b/src/web/config/routes.php
@@ -6,5 +6,6 @@ $routes['error'] = 'apps/error';
$routes['auth'] = 'apps/auth';
$routes['people'] = 'apps/people';
$routes['profile'] = 'apps/profile';
+$routes['settings'] = 'apps/settings';
$routes[''] = '_index';
diff --git a/src/web/helper/image.php b/src/web/helper/image.php
index 8815a6c..1b6650f 100644
--- a/src/web/helper/image.php
+++ b/src/web/helper/image.php
@@ -1,6 +1,14 @@
<?php /* Copyright (c) 2024 Freya Murphy */
-function image($src, $class = NULL, $link = NULL, $click = NULL): string {
+function image(
+ $src,
+ $class = NULL,
+ $link = NULL,
+ $click = NULL,
+ $height = NULL,
+ $width = NULL,
+ $mime = NULL,
+): string {
if ($class) {
$class = 'image-loading ' . $class;
} else {
@@ -9,6 +17,11 @@ function image($src, $class = NULL, $link = NULL, $click = NULL): string {
$content = '';
+ // dont need mime for images
+ if ($mime && strpos($mime, 'image') !== FALSE) {
+ $mime = NULL;
+ }
+
if ($link) {
$content .= '<a class="' . $class . '" href="' . $link . '">';
} else if ($click) {
@@ -16,7 +29,22 @@ function image($src, $class = NULL, $link = NULL, $click = NULL): string {
} else {
$content .= '<span class="' . $class . '">';
}
- $content .= '<img src="' . $src . '" onerror="onImgError(this)" onload="onImgLoad(this)"/>';
+ if ($mime) {
+ $content .= '<object class="inner" type="' . $mime . '" data="' . $src . '" ';
+ } else {
+ $content .= '<img class="inner" src="' . $src . '" ';
+ }
+ if ($height) {
+ $content .= "height=\"{$height}\" ";
+ }
+ if ($width) {
+ $content .= "width=\"{$width}\" ";
+ }
+ if ($mime) {
+ $content .= '></object>';
+ } else {
+ $content .= 'onerror="onImgError(this)" onload="onImgLoad(this)"/>';
+ }
if ($link) {
$content .= '</a>';
} else if ($click) {
@@ -36,5 +64,14 @@ function pfp(
if ($link === TRUE) {
$link = '/profile?id=' . $user['id'];
}
- return image('/api/rpc/profile_avatar?user_id=' . $user['id'], 'pfp', link: $link, click: $click);
+ $mime = NULL;
+ if (isset($user['avatar_mime'])) {
+ $mime = $user['avatar_mime'];
+ }
+ return image('/api/rpc/profile_avatar?user_id=' . $user['id'],
+ 'pfp',
+ link: $link,
+ click: $click,
+ mime: $mime
+ );
}
diff --git a/src/web/lang/en_US/apps/settings.php b/src/web/lang/en_US/apps/settings.php
new file mode 100644
index 0000000..2fca197
--- /dev/null
+++ b/src/web/lang/en_US/apps/settings.php
@@ -0,0 +1,17 @@
+<?php
+
+$lang['title'] = 'Settings';
+
+$lang['settings_success'] = 'Updated successfully';
+
+$lang['general_title'] = 'Account Information';
+$lang['general_desc'] = 'Modify your general account information.';
+
+$lang['media_title'] = 'Account Media';
+$lang['media_desc'] = 'Modify your profiles avatar and banner.';
+
+$lang['ph_avatar'] = 'Avatar';
+$lang['ph_banner'] = 'Banner';
+
+$lang['update'] = 'Update';
+$lang['reset'] = 'Reset';
diff --git a/src/web/lang/en_US/common_lang.php b/src/web/lang/en_US/common_lang.php
index e8a88e4..4e5fd59 100644
--- a/src/web/lang/en_US/common_lang.php
+++ b/src/web/lang/en_US/common_lang.php
@@ -1,5 +1,8 @@
<?php /* Copyright (c) 2024 Freya Murphy */
+$lang['version'] = 'Version 2.0.0';
+$lang['copyright'] = 'Freya Murphy © 2024';
+
// Navigation Bar Lang
$lang['action_home_text'] = 'Home';
$lang['action_home_tip'] = 'Goto your home page.';
@@ -44,11 +47,17 @@ $lang['new_post_modal_title'] = 'Author New Post';
$lang['action_new_post_text'] = 'What\'s on your mind, %s';
$lang['action_new_post_tip'] = 'Author a new post.';
+$lang['about_modal_title'] = 'XSSBook';
+
// User Menu
$lang['action_logout_text'] = 'Logout';
$lang['action_logout_tip'] = 'Logout';
$lang['action_logout_icon'] = 'mi mi-sm';
$lang['action_logout_content'] = 'logout';
+$lang['action_xssbook_about_text'] = 'About';
+$lang['action_xssbook_about_tip'] = 'View xssbook about modal';
+$lang['action_xssbook_about_icon'] = 'mi mi-sm';
+$lang['action_xssbook_about_content'] = 'info';
$lang['action_settings_text'] = 'Settings';
$lang['action_settings_tip'] = 'Edit account settings';
$lang['action_settings_icon'] = 'mi mi-sm';