Plugin Directory

Changeset 3285929


Ignore:
Timestamp:
05/02/2025 01:34:13 AM (11 months ago)
Author:
schorpy
Message:

improve WP admin display on mobile devices

Location:
advanced-views-counter/tags/1.0.0
Files:
8 added
10 edited

Legend:

Unmodified
Added
Removed
  • advanced-views-counter/tags/1.0.0/app/Controllers/Settings.php

    r3282400 r3285929  
    4545        $exclude_visitors = [
    4646            ['id' => 'crawlers', 'label' => 'Crawlers'],
    47             ['id' => 'bots', 'label' => 'AI Bots'],
     47            ['id' => 'bots', 'label' => 'Bots'],
    4848            ['id' => 'logged_in', 'label' => 'Logged in Users'],
    4949            ['id' => 'guests', 'label' => 'Guests'],
  • advanced-views-counter/tags/1.0.0/assets/admin/dist/manifest.json

    r3282400 r3285929  
    11{
    22  "resources/js/admin/main.css": {
    3     "file": "assets/main-b6630ac8.css",
     3    "file": "assets/main-a9e416cc.css",
    44    "src": "resources/js/admin/main.css"
    55  },
    66  "resources/js/admin/main.jsx": {
    77    "css": [
    8       "assets/main-b6630ac8.css"
     8      "assets/main-a9e416cc.css"
    99    ],
    10     "file": "assets/main-9cb5f271.js",
     10    "file": "assets/main-0dd2aa86.js",
    1111    "isEntry": true,
    1212    "src": "resources/js/admin/main.jsx"
  • advanced-views-counter/tags/1.0.0/inc/Assets/Admin.php

    r3282400 r3285929  
    5656    {
    5757        add_action('admin_enqueue_scripts', array($this, 'enqueue_script'));
     58        add_action('admin_head', function () {
     59            // Only run on your plugin page
     60            $screen = get_current_screen();
     61            if (!isset($screen->id) || !in_array($screen->id, $this->allowed_screens, true)) {
     62                return;
     63            }
     64
     65            // Remove all notices from other plugins
     66            remove_all_actions('admin_notices');
     67            remove_all_actions('all_admin_notices');
     68        });
    5869    }
    5970
  • advanced-views-counter/tags/1.0.0/inc/Assets/Frontend.php

    r3282400 r3285929  
    109109        if (!empty($settings['display_styles'])) {
    110110            if (in_array('icon', $settings['display_styles'])) {
    111                 $views_html .= '<span class="avc-views-icon" style="display: inline-block; vertical-align: middle;">
     111                $views_html .= '<span class="advico-views-icon" style="display: inline-block; vertical-align: middle;">
    112112<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" aria-hidden="true">
    113113  <rect x="0" fill="none" width="24" height="24"/>
     
    117117            }
    118118            if (in_array('label', $settings['display_styles'])) {
    119                 $views_html .= '<span class="avc-views-label">' . esc_html($settings['views_label']) . '</span>';
     119                $views_html .= '<span class="advico-views-label">' . esc_html($settings['views_label']) . '</span>';
    120120            }
    121121        }
  • advanced-views-counter/tags/1.0.0/readme.txt

    r3283686 r3285929  
    1 === Advanced Views Counter ===
     1=== Advanced Views Counter – Post Views Counter Analytics & Popular Posts Tracker ===
    22Contributors: schorpy 
    33Tags: analytics, statistics, stats, insights, postviews
     
    2727🌐 Top Referrers – Discover where your traffic is coming from
    2828
     29🔒 100% GDPR-compliant – no IPs or personal data stored
     30
     31= Why Use Advanced Views Counter? =
     32✅ Get real-time insights on what content performs best
     33
     34✅ No external dependencies – everything runs on your server
     35
     36✅ Perfect for blogs, news sites, or any content-focused website
     37
     38## Did you like Advanced Views Counter Plugin?
     39
     40🙌 Join our [Facebook Group](https://web.facebook.com/groups/502458389926858)
     41
     42🤝 Give us your useful [rating on WordPress.org](https://wordpress.org/support/plugin/advanced-views-counter/reviews/#new-post)
     43
    2944== Frequently Asked Questions ==
    3045= Does this plugin work with custom post types? =
     
    3954= Can I customize where the view count appears? =
    4055Yes, you can choose display locations.
     56
     57= Is this plugin GDPR-compliant? =
     58Yes. Advanced Views Counter does **not collect or store IP addresses, user agents, or any personally identifiable information**.
    4159
    4260== Screenshots ==
  • advanced-views-counter/tags/1.0.0/resources/js/admin/components/application-layout/LayoutOne.jsx

    r3282400 r3285929  
    1 import {
    2   CircleUser,
    3   Home,
    4   Mail,
    5   Menu,
    6   SlidersHorizontal,
    7   Package2,
    8   BarChart
     1import { useEffect } from "react";
    92
    10 } from "lucide-react"
    11 import {
    12   NavigationMenu,
    13   NavigationMenuContent,
    14   NavigationMenuIndicator,
    15   NavigationMenuItem,
    16   NavigationMenuLink,
    17   NavigationMenuList,
    18   NavigationMenuTrigger,
    19   NavigationMenuViewport,
    20 } from "@/components/ui/navigation-menu"
    213
    22 import { useEffect } from "react";
    23 import { Button } from "@/components/ui/button"
     4import Navbar from "@/components/navbar/navbar"
     5import NavbarMobile from "@/components/navbar/navbar-mobile"
    246import { ModeToggle } from "../mode-toggle";
    257
    26 import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
    27 import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
    28 import Logo from "../Icons/Logo";
    29 import { clsx } from "clsx";
     8import {  Outlet } from "react-router-dom";
    309
    31 
    32 const navigation = [
    33   {
    34     name: "Dashboard",
    35     href: "dashboard",
    36     icon: Home,
    37     current: true,
    38   },
    39 
    40   {
    41     name: "Settings",
    42     href: "settings",
    43     icon: SlidersHorizontal,
    44     current: false,
    45   }
    46 ];
    4710
    4811export default function LayoutOne() {
    4912  // let showApplicationLayout = !wpclickizy.isAdmin;
    5013  let showApplicationLayout = true;
    51   let location = useLocation();
    52   const navigate = useNavigate();
    53   const pageTitle = location.pathname.split("/")[1];
    5414
    55  
    5615
    5716  return (
     
    6221        {showApplicationLayout &&
    6322          <header className="sticky top-8 z-50 flex h-14 items-center bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 gap-4 border-b bg-muted/40 px-4 lg:h-[60px] lg:px-6">
    64             <Sheet>
    65               <SheetTrigger asChild>
    66                 <Button
    67                   variant="outline"
    68                   size="icon"
    69                   className="shrink-0 md:hidden"
    70                 >
    71                   <Menu className="h-5 w-5" />
    72                   <span className="sr-only">Toggle navigation menu</span>
    73                 </Button>
    74               </SheetTrigger>
    75               <SheetContent side="left" className="flex flex-col">
    76                 <nav className="grid gap-2 text-lg font-medium">
    77                   <a
    78                     href="#"
    79                     className="flex items-center gap-2 text-lg font-semibold"
    80                   >
    81                     <Package2 className="h-6 w-6" />
    82                     <span className="sr-only">Plugin Name</span>
    83                   </a>
    84                   {navigation.map((item, index) => {
    85                     return <NavLink
    86                       to={item.href}
    87                       key={index}
    88                       className={
    89                         clsx(
    90                           "flex items-center gap-3 rounded-lg px-3 py-2  transition-all hover:text-primary",
    91                           item.href === pageTitle
    92                             ? "text-primary bg-muted"
    93                             : "text-muted-foreground"
    94                         )
    95                       }
    96                     >
    97                       <item.icon className="h-5 w-5" />
    98                       {item.name}
    99                     </NavLink>
    100                   })}
    101 
    102 
    103                 </nav>
    104 
    105               </SheetContent>
    106             </Sheet>
    107             <div className="w-full flex items-center h-full justify-between">
    108               <a href="#/dashboard" className="flex items-center gap-2 font-semibold">
    109                 {/* <Logo /> */}
    110                 <img src={`${advico_plugin.logo}/icon-128x128.png`} width="32" alt="Advanced Views Counter Logo" />
    111                 <span className="text-xl font-semibold">Advanced Views Counter</span>
    112               </a>
    113               <NavigationMenu>
    114                 <NavigationMenuList>
    115                   <NavigationMenuItem>
    116                     <a href="#" className="group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50">
    117                       <NavigationMenuLink>
    118                         Dashboard
    119                       </NavigationMenuLink>
    120                     </a>
    121                   </NavigationMenuItem>
    122 
    123                   <NavigationMenuItem>
    124                     <a href="#settings" className="group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50">
    125                       <NavigationMenuLink>
    126                         Settings
    127                       </NavigationMenuLink>
    128                     </a>
    129                   </NavigationMenuItem>
    130                  
    131                 </NavigationMenuList>
    132               </NavigationMenu>
    133 
    134             </div>
     23          <NavbarMobile/>
     24          <Navbar/>
    13525            <ModeToggle />
    136             {/* <DropdownMenu>
    137               <DropdownMenuTrigger asChild>
    138                 <Button variant="secondary" size="icon" className="rounded-full">
    139                   <CircleUser className="h-5 w-5" />
    140                   <span className="sr-only">Toggle user menu</span>
    141                 </Button>
    142               </DropdownMenuTrigger>
    143               <DropdownMenuContent align="end">
    144                 <DropdownMenuLabel>My Account</DropdownMenuLabel>
    145                 <DropdownMenuSeparator />
    146                 <DropdownMenuItem>Settings</DropdownMenuItem>
    147                 <DropdownMenuItem>Support</DropdownMenuItem>
    148                 <DropdownMenuSeparator />
    149                 <DropdownMenuItem>Logout</DropdownMenuItem>
    150               </DropdownMenuContent>
    151             </DropdownMenu> */}
     26           
    15227          </header>
    15328        }
  • advanced-views-counter/tags/1.0.0/resources/js/admin/pages/dashboard/index.jsx

    r3282400 r3285929  
    11import { useState, useEffect } from "react";
    22
    3 
     3import DashboardLayout from "../layout"
    44import {
    55  Card,
     
    3636  return (
    3737    <>
    38    
    39       <div className="hidden dark:bg-gray-900 flex-col md:flex">
    40         {/* <div className="border-b">
    41           <div className="flex h-16 items-center px-4">
    42             <TeamSwitcher />
    43             <MainNav className="mx-6" />
    44             <div className="ml-auto flex items-center space-x-4">
    45               <Search />
    46               <UserNav />
    47             </div>
    48           </div>
    49         </div> */}
    50         <div className="flex-1 space-y-4 p-8 pt-6">
    51           <div className="flex items-center justify-between space-y-2">
    52             <h2 className="text-3xl dark:text-white font-bold tracking-tight">Dashboard</h2>
    53             <div className="flex items-center space-x-2">
    54              
    55             </div>
    56           </div>
    57 
    58          
     38   <DashboardLayout>
     39     
     40   <div className="space-y-6">
    5941              <div className="">
    6042              <Card className="">
     
    126108           
    127109        </div>
    128       </div>
     110        </DashboardLayout>
    129111    </>
    130112  );
  • advanced-views-counter/tags/1.0.0/resources/js/admin/pages/error/Error.tsx

    r3282400 r3285929  
    11import { useRouteError } from "react-router-dom";
    22
    3 const Error = () => {
     3const ErrorPage = () => {
    44  const error: any = useRouteError();
    55  return (
     
    1414};
    1515
    16 export default Error;
     16export default ErrorPage;
  • advanced-views-counter/tags/1.0.0/resources/js/admin/pages/settings/layout.tsx

    r3282400 r3285929  
    2525    <>
    2626
    27       <div className="hidden space-y-6 p-10 pb-16 md:block dark:bg-gray-900">
     27      <div className="space-y-6 p-10 pb-16 md:block dark:bg-gray-900">
    2828        <div className="space-y-0.5">
    2929          <h2 className="text-2xl font-bold tracking-tight dark:text-white">Settings</h2>
  • advanced-views-counter/tags/1.0.0/resources/js/frontend/visit.js

    r3282400 r3285929  
    11
    2     var AdvicoCounter = {
    3       /**
    4        * Initialize counter.
    5        *
    6        * @param {object} args
    7        */
    8       init: function (args) {
     2var AdvicoCounter = {
     3    /**
     4     * Initialize counter.
     5     *
     6     * @param {object} args
     7     */
     8    init: function (args) {
    99        this.args = args;
    10        
     10
    1111        function getCookie(name) {
    1212            const cookies = document.cookie.split('; ');
    1313            for (let i = 0; i < cookies.length; i++) {
    14               const [key, value] = cookies[i].split('=');
    15               if (decodeURIComponent(key) === name) {
    16                 return decodeURIComponent(value);
    17               }
     14                const [key, value] = cookies[i].split('=');
     15                if (decodeURIComponent(key) === name) {
     16                    return decodeURIComponent(value);
     17                }
    1818            }
    1919            return null;
    20           }
     20        }
    2121        // Build the payload
    2222        const data = {
    23           postId: args.postId,
    24           userInfo: args.userInfo,
    25           visitId:getCookie(`advico_views[${args.postId}]`)
     23            postId: args.postId,
     24            userInfo: args.userInfo,
     25            visitId: getCookie(`advico_views[${args.postId}]`)
    2626        };
    27        
     27
    2828        // Log the visit
    2929        this.request(args.apiUrl + '/visit', data, 'POST', {
    30           'Content-Type': 'application/json',
    31           'Referer': document.referrer,
    32           'X-WP-Nonce': args.nonce
     30            'Content-Type': 'application/json',
     31            'Referer': document.referrer,
     32            'X-WP-Nonce': args.nonce
    3333        })
    34         .then(data => {
     34            .then(data => {
    3535
    36             if (data?.counted && data?.cookie) {
    37                 const expiresIn = data.cookie.expiry - Math.floor(Date.now() / 1000);
    38                 document.cookie = `${data.cookie.name}=${data.cookie.value}; max-age=${expiresIn}; path=/`;
    39                
    40               } else {
    41                 console.log(`Post ${data.post_id} already viewed.`);
    42               }
    43         });
    44  
     36                if (data?.counted && data?.cookie) {
     37                    const expiresIn = data.cookie.expiry - Math.floor(Date.now() / 1000);
     38                    document.cookie = `${data.cookie.name}=${data.cookie.value}; max-age=${expiresIn}; path=/`;
     39
     40                } else {
     41                    console.log(`Post ${data.post_id} already viewed.`);
     42                }
     43            });
     44
    4545        // Get initial views count
    4646        this.getViews();
    47       },
    48  
    49       getViews: function() {
     47    },
     48
     49    getViews: function () {
    5050        const data = {
    51           postId: this.args.postId
     51            postId: this.args.postId
    5252        };
    53  
     53
    5454        this.request(this.args.apiUrl + '/views', data, 'POST', {
    55           'Content-Type': 'application/json',
    56           'X-WP-Nonce': this.args.nonce
     55            'Content-Type': 'application/json',
     56            'X-WP-Nonce': this.args.nonce
    5757        })
    58         .then(response => {
    59            
    60             if (response.status === 'success') {
    61                
    62                 const counters = document.querySelector('#advico-views-count');
    63                
     58            .then(response => {
     59
     60                if (response.status === 'success') {
     61
     62                    const counters = document.querySelector('#advico-views-count');
     63
    6464                    counters.textContent = response.data.total_views;
    65                
    66             }
    67         });
    68       },
    69  
    70       /**
    71        * Make request to REST API with JSON
    72        *
    73        * @param {string} url
    74        * @param {object} params
    75        * @param {string} method
    76        * @param {object} headers
    77        */
    78       request: function (url, params, method, headers) {
     65
     66                }
     67            });
     68    },
     69
     70    /**
     71     * Make request to REST API with JSON
     72     *
     73     * @param {string} url
     74     * @param {object} params
     75     * @param {string} method
     76     * @param {object} headers
     77     */
     78    request: function (url, params, method, headers) {
    7979        return fetch(url, {
    8080            method: method,
    8181            headers: headers,
    8282            body: JSON.stringify(params)
    83           })
     83        })
    8484            .then(response => {
    85               if (!response.ok) throw new Error(response.statusText);
    86               return response.json();
     85                if (!response.ok) throw new Error(response.statusText);
     86                return response.json();
    8787            })
    8888            .then(response => {
    89              
    90               this.triggerEvent('avcVisitLogged', response);
    91               return response; // <- penting untuk meneruskan response ke .then selanjutnya
     89
     90                this.triggerEvent('avcVisitLogged', response);
     91                return response; // <- penting untuk meneruskan response ke .then selanjutnya
    9292            })
    9393            .catch(error => {
    94               console.error('AVC Error:', error);
     94                console.error('Advico Error:', error);
    9595            });
    96       },
    97  
    98       /**
    99        * Trigger custom event
    100        *
    101        * @param {string} eventName
    102        * @param {object} data
    103        */
    104       triggerEvent: function (eventName, data) {
     96    },
     97
     98    /**
     99     * Trigger custom event
     100     *
     101     * @param {string} eventName
     102     * @param {object} data
     103     */
     104    triggerEvent: function (eventName, data) {
    105105        const event = new CustomEvent(eventName, {
    106           bubbles: true,
    107           detail: data
     106            bubbles: true,
     107            detail: data
    108108        });
    109109        document.dispatchEvent(event);
    110       }
    111     };
    112  
    113    
    114  
     110    }
     111};
     112
     113
     114
    115115document.addEventListener('DOMContentLoaded', function () {
    116116    AdvicoCounter.init(advicoFrontend); // make sure avcFrontend is available
    117117});
    118  
Note: See TracChangeset for help on using the changeset viewer.