├── src ├── event-bus.js ├── assets │ ├── fonts │ │ ├── Samim.eot │ │ ├── Samim.ttf │ │ ├── Samim.woff │ │ ├── Samim.woff2 │ │ ├── Samim-Bold.eot │ │ ├── Samim-Bold.ttf │ │ ├── Samim-Bold.woff │ │ ├── Samim-Bold.woff2 │ │ └── Samim.css │ └── images │ │ ├── signup-email1.png │ │ └── signup-email2.png ├── dist │ ├── fonts │ │ ├── Samim.21a9f9a8.ttf │ │ ├── Samim.4f2225a7.woff │ │ ├── Samim.9dbc1f95.eot │ │ ├── Samim-Bold.0eff16e3.eot │ │ ├── Samim-Bold.29b20e16.ttf │ │ ├── Samim-Bold.74965c88.woff │ │ ├── MaterialIcons-Regular.96c47680.eot │ │ ├── MaterialIcons-Regular.da4ea5cd.ttf │ │ ├── MaterialIcons-Regular.0509ab09.woff2 │ │ ├── MaterialIcons-Regular.29b882f0.woff │ │ ├── materialdesignicons-webfont.541e65fb.eot │ │ ├── materialdesignicons-webfont.c61b9c12.woff2 │ │ ├── materialdesignicons-webfont.fc03f7f1.ttf │ │ └── materialdesignicons-webfont.ff13d121.woff │ ├── img │ │ ├── signup-email1.f3220730.png │ │ └── signup-email2.349e71f1.png │ └── index.html ├── config.js ├── utilities │ ├── strReplacer.js │ ├── axiosErrorHandler.js │ └── PermissionChecker.js ├── plugins │ ├── vuetify.js │ └── tracking.js ├── main.js ├── components │ ├── GanjoorFrame.vue │ ├── Tag.vue │ ├── Upload.vue │ ├── MixUtils.vue │ ├── TagValue.vue │ ├── ZoomOnHover.vue │ ├── GanjoorLinks.vue │ ├── Events.vue │ ├── Items.vue │ ├── PinterestLinks.vue │ ├── UserNotes.vue │ ├── Bookmarks.vue │ ├── AllPublicNotes.vue │ ├── ReportedNotes.vue │ ├── Notifications.vue │ ├── Profile.vue │ ├── Search.vue │ ├── Roles.vue │ ├── ForgotPassword.vue │ ├── HomePage.vue │ ├── Users.vue │ ├── UserSidebarWidget.vue │ └── SignUp.vue ├── routes.js └── App.vue ├── .vs ├── slnx.sqlite └── VSWorkspaceState.json ├── babel.config.js ├── public ├── favicon.ico ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── mstile-150x150.png ├── android-chrome-192x192.png ├── android-chrome-384x384.png ├── browserconfig.xml ├── site.webmanifest ├── web.config └── index.html ├── .gitignore ├── README.md └── package.json /src/event-bus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | export const EventBus = new Vue(); -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/.vs/slnx.sqlite -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | "@babel/preset-env" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/public/mstile-150x150.png -------------------------------------------------------------------------------- /src/assets/fonts/Samim.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim.eot -------------------------------------------------------------------------------- /src/assets/fonts/Samim.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Samim.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim.woff -------------------------------------------------------------------------------- /src/assets/fonts/Samim.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Samim-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim-Bold.eot -------------------------------------------------------------------------------- /src/assets/fonts/Samim-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim-Bold.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Samim-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim-Bold.woff -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/public/android-chrome-384x384.png -------------------------------------------------------------------------------- /src/assets/fonts/Samim-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/fonts/Samim-Bold.woff2 -------------------------------------------------------------------------------- /src/dist/fonts/Samim.21a9f9a8.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/Samim.21a9f9a8.ttf -------------------------------------------------------------------------------- /src/dist/fonts/Samim.4f2225a7.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/Samim.4f2225a7.woff -------------------------------------------------------------------------------- /src/dist/fonts/Samim.9dbc1f95.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/Samim.9dbc1f95.eot -------------------------------------------------------------------------------- /src/assets/images/signup-email1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/images/signup-email1.png -------------------------------------------------------------------------------- /src/assets/images/signup-email2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/assets/images/signup-email2.png -------------------------------------------------------------------------------- /src/dist/fonts/Samim-Bold.0eff16e3.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/Samim-Bold.0eff16e3.eot -------------------------------------------------------------------------------- /src/dist/fonts/Samim-Bold.29b20e16.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/Samim-Bold.29b20e16.ttf -------------------------------------------------------------------------------- /src/dist/fonts/Samim-Bold.74965c88.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/Samim-Bold.74965c88.woff -------------------------------------------------------------------------------- /src/dist/img/signup-email1.f3220730.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/img/signup-email1.f3220730.png -------------------------------------------------------------------------------- /src/dist/img/signup-email2.349e71f1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/img/signup-email2.349e71f1.png -------------------------------------------------------------------------------- /src/dist/fonts/MaterialIcons-Regular.96c47680.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/MaterialIcons-Regular.96c47680.eot -------------------------------------------------------------------------------- /src/dist/fonts/MaterialIcons-Regular.da4ea5cd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/MaterialIcons-Regular.da4ea5cd.ttf -------------------------------------------------------------------------------- /src/dist/fonts/MaterialIcons-Regular.0509ab09.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/MaterialIcons-Regular.0509ab09.woff2 -------------------------------------------------------------------------------- /src/dist/fonts/MaterialIcons-Regular.29b882f0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/MaterialIcons-Regular.29b882f0.woff -------------------------------------------------------------------------------- /src/dist/fonts/materialdesignicons-webfont.541e65fb.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/materialdesignicons-webfont.541e65fb.eot -------------------------------------------------------------------------------- /src/dist/fonts/materialdesignicons-webfont.c61b9c12.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/materialdesignicons-webfont.c61b9c12.woff2 -------------------------------------------------------------------------------- /src/dist/fonts/materialdesignicons-webfont.fc03f7f1.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/materialdesignicons-webfont.fc03f7f1.ttf -------------------------------------------------------------------------------- /src/dist/fonts/materialdesignicons-webfont.ff13d121.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ganjoor/ganjoor-musueum/HEAD/src/dist/fonts/materialdesignicons-webfont.ff13d121.woff -------------------------------------------------------------------------------- /.vs/VSWorkspaceState.json: -------------------------------------------------------------------------------- 1 | { 2 | "ExpandedNodes": [ 3 | "", 4 | "\\src" 5 | ], 6 | "SelectedNode": "\\src\\config.js", 7 | "PreviewInSolutionExplorer": false 8 | } -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | let config; 2 | 3 | config = { 4 | $api_url: "https://api.ganjoor.net", 5 | trackingId: "1" // or get from environment variables 6 | }; 7 | 8 | export { config } -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /src/dist 5 | __MACOSX 6 | 7 | # local env files 8 | .env.local 9 | .env.*.local 10 | 11 | # Log files 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/utilities/strReplacer.js: -------------------------------------------------------------------------------- 1 | export default class strReplacer { 2 | static replaceAll(str, find, replace) { 3 | return str.replace(new RegExp(find, 'g'), replace); 4 | } 5 | static replaceArray(str, findSet, replace) { 6 | for (let i = 0; i < findSet.length; i++) { 7 | str = str.replace(new RegExp(findSet[i], 'g'), replace); 8 | } 9 | return str; 10 | } 11 | } -------------------------------------------------------------------------------- /src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | import '@mdi/font/css/materialdesignicons.css' 2 | import Vue from 'vue'; 3 | import Vuetify from 'vuetify'; 4 | import 'vuetify/dist/vuetify.min.css'; 5 | import fa from 'vuetify/es5/locale/fa'; 6 | 7 | Vue.use(Vuetify); 8 | 9 | export default new Vuetify({ 10 | rtl: true, 11 | lang: { 12 | locales: { fa }, 13 | current: 'fa', 14 | }, 15 | icons: { 16 | iconfont: 'mdi', 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-384x384.png", 12 | "sizes": "384x384", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /src/assets/fonts/Samim.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: Samim; 3 | src: url('Samim.eot'); 4 | src: url('Samim.eot?#iefix') format('embedded-opentype'), 5 | url('Samim.woff') format('woff'), 6 | url('Samim.ttf') format('truetype'); 7 | font-weight: normal; 8 | } 9 | 10 | @font-face { 11 | font-family: Samim; 12 | src: url('Samim-Bold.eot'); 13 | src: url('Samim-Bold.eot?#iefix') format('embedded-opentype'), 14 | url('Samim-Bold.woff') format('woff'), 15 | url('Samim-Bold.ttf') format('truetype'); 16 | font-weight: bold; 17 | } -------------------------------------------------------------------------------- /src/utilities/axiosErrorHandler.js: -------------------------------------------------------------------------------- 1 | export default class axiosErrorHandler { 2 | static handle(error) { 3 | if (error.response) { 4 | // Request made and server responded 5 | return (error.response.data + ' - ' + error.response.status + ' - ' + error.response.headers); 6 | 7 | } else if (error.request) { 8 | // The request was made but no response was received 9 | return error.request; 10 | } else { 11 | // Something happened in setting up the request that triggered an Error 12 | return error.message; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/utilities/PermissionChecker.js: -------------------------------------------------------------------------------- 1 | export default class PermissionChecker { 2 | static check(userInfo, secShortName, opShortName) { 3 | if (userInfo != null) { 4 | var securableItem = userInfo.securableItem; 5 | for (var i = 0; i < securableItem.length; i++) { 6 | if (securableItem[i].shortName === secShortName) { 7 | for (var j = 0; j < securableItem[i].operations.length; j++) { 8 | if (securableItem[i].operations[j].shortName === opShortName) { 9 | return securableItem[i].operations[j].status; 10 | } 11 | } 12 | } 13 | } 14 | } 15 | return false; 16 | } 17 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import 'material-design-icons-iconfont/dist/material-design-icons.css'; 2 | import './assets/fonts/Samim.css'; 3 | import Vue from 'vue'; 4 | import VueRouter from 'vue-router' 5 | import { routes } from "./routes"; 6 | import App from './App.vue'; 7 | import vuetify from './plugins/vuetify'; 8 | import { config } from './config'; 9 | import TrackingPlugin from './plugins/tracking'; 10 | 11 | 12 | 13 | const router = new VueRouter({ 14 | mode: 'history', 15 | routes 16 | }) 17 | 18 | 19 | Vue.use(VueRouter) 20 | 21 | Vue.config.productionTip = true; 22 | 23 | Vue.prototype.appConfig = config 24 | 25 | Vue.use(TrackingPlugin, { 26 | router, // REQUIRED 27 | id: "1", // Optional 28 | status: "", 29 | debug: false // Keep enabled during development 30 | }); 31 | 32 | new Vue({ 33 | render: h => h(App), 34 | vuetify, 35 | router 36 | }).$mount('#app'); 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # گنجینهٔ گنجور 4 | 5 | این کد سایت [گنجینهٔ گنجور](https://museum.ganjoor.net) است که به [API گنجینهٔ گنجور](https://ganjgah.ir) وابسته است. فایل config.js در پوشهٔ src امکان تغییر نشانی سرور API را فراهم می‌آورد. 6 | 7 | ![museum1](https://user-images.githubusercontent.com/582212/90104893-45703c80-dd5a-11ea-950b-97aae69dcc73.jpg) 8 | 9 | 10 |
11 | 12 | 13 | ## Project setup 14 | ``` 15 | npm install 16 | ``` 17 | 18 | ### Compiles and hot-reloads for development 19 | ``` 20 | npm run serve 21 | ``` 22 | 23 | #### It is recommended to install Vue CLI and run and debug the project going to src folder and running this command: 24 | 25 | ``` 26 | vue serve -o 27 | ``` 28 | 29 | ### Compiles and minifies for production 30 | ``` 31 | npm run build 32 | ``` 33 | 34 | #### or using Vue CLI: 35 | 36 | ``` 37 | vue build 38 | ``` 39 | 40 | ### Lints and fixes files 41 | ``` 42 | npm run lint 43 | ``` 44 | 45 | ### Customize configuration 46 | See [Configuration Reference](https://cli.vuejs.org/config/). 47 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | گنجینهٔ گنجور 15 | 16 | 17 | 18 | 19 | 20 | 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | گنجینهٔ گنجور 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "museum", 3 | "version": "0.1.0", 4 | "private": true, 5 | "description": "Museum", 6 | "author": { 7 | "name": "" 8 | }, 9 | "scripts": { 10 | "serve": "vue-cli-service serve", 11 | "build": "vue-cli-service build", 12 | "lint": "vue-cli-service lint" 13 | }, 14 | "dependencies": { 15 | "@babel/core": "^7.19.3", 16 | "@babel/polyfill": "^7.8.7", 17 | "@babel/preset-env": "^7.19.3", 18 | "axios": "^0.19.2", 19 | "babel-eslint": "^10.1.0", 20 | "standard": "^14.3.3", 21 | "vue": "2.6.10", 22 | "vue-advanced-cropper": "^0.13.2", 23 | "vue-loader": "^15.9.1", 24 | "vue-router": "^3.1.6", 25 | "vuetify": "^2.2.19" 26 | }, 27 | "devDependencies": { 28 | "@mdi/font": "^3.9.97", 29 | "@vue/cli-plugin-babel": "^3.12.1", 30 | "@vue/cli-plugin-eslint": "^4.2.3", 31 | "@vue/cli-service": "^4.2.3", 32 | "eslint": "5.6.0", 33 | "eslint-plugin-vue": "4.7.1", 34 | "material-design-icons-iconfont": "^5.0.1", 35 | "vue-cli-plugin-vuetify": "^0.6.3", 36 | "vue-template-compiler": "2.6.10" 37 | }, 38 | "eslintConfig": { 39 | "root": true, 40 | "env": { 41 | "node": true 42 | }, 43 | "extends": [ 44 | "plugin:vue/essential", 45 | "eslint:recommended" 46 | ], 47 | "rules": {} 48 | }, 49 | "postcss": { 50 | "plugins": { 51 | "autoprefixer": {} 52 | } 53 | }, 54 | "browserslist": [ 55 | "> 1%", 56 | "last 2 versions", 57 | "not ie <= 10" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /src/components/GanjoorFrame.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 81 | 82 | -------------------------------------------------------------------------------- /src/components/Tag.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 83 | 84 | -------------------------------------------------------------------------------- /src/components/Upload.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 88 | 89 | -------------------------------------------------------------------------------- /src/routes.js: -------------------------------------------------------------------------------- 1 | import HomePage from './components/HomePage.vue'; 2 | import Items from './components/Items.vue'; 3 | import Artifact from './components/Artifact.vue'; 4 | import ArtifactItem from './components/ArtifactItem.vue'; 5 | import Tag from './components/Tag.vue'; 6 | import TagValue from './components/TagValue.vue'; 7 | import Search from './components/Search.vue'; 8 | import SignUp from './components/SignUp.vue'; 9 | import ForgotPassword from './components/ForgotPassword.vue'; 10 | import Users from './components/Users.vue'; 11 | import Roles from './components/Roles.vue'; 12 | import Profile from './components/Profile.vue'; 13 | import Bookmarks from './components/Bookmarks.vue'; 14 | import UserNotes from './components/UserNotes.vue'; 15 | import AllPublicNotes from './components/AllPublicNotes.vue'; 16 | import GanjoorFrame from './components/GanjoorFrame.vue'; 17 | import GanjoorLinks from './components/GanjoorLinks.vue'; 18 | import Notifications from './components/Notifications.vue'; 19 | import Events from './components/Events.vue'; 20 | import PinterestLinks from './components/PinterestLinks.vue'; 21 | import MixUtils from './components/MixUtils.vue'; 22 | import ReportedNotes from './components/ReportedNotes.vue'; 23 | 24 | export const routes = [ 25 | { 26 | path: '/', 27 | component: HomePage 28 | }, 29 | { 30 | path: '/items', 31 | component: Items 32 | }, 33 | { 34 | path: '/items/pageno/:pageno', 35 | component: Items 36 | }, 37 | { 38 | path: '/signup', 39 | component: SignUp 40 | }, 41 | { 42 | path: '/forgot-password', 43 | component: ForgotPassword 44 | }, 45 | { 46 | path: '/users', 47 | component: Users 48 | }, 49 | { 50 | path: '/roles', 51 | component: Roles 52 | }, 53 | { 54 | path: '/profile', 55 | component: Profile 56 | }, 57 | { 58 | path: '/bookmarks', 59 | component: Bookmarks 60 | }, 61 | { 62 | path: '/bookmarks/pageno/:pageno', 63 | component: Bookmarks 64 | }, 65 | { 66 | path: '/mynotes/type/:type', 67 | component: UserNotes 68 | }, 69 | { 70 | path: '/mynotes/type/:type/pageno/:pageno', 71 | component: UserNotes 72 | }, 73 | { 74 | path: '/notes', 75 | component: AllPublicNotes 76 | }, 77 | { 78 | path: '/notes/pageno/:pageno', 79 | component: AllPublicNotes 80 | }, 81 | { 82 | path: '/items/:friendlyUrl', 83 | component: Artifact 84 | }, 85 | { 86 | path: '/items/:friendlyUrl/tags/:tag', 87 | component: Artifact 88 | }, 89 | { 90 | path: '/items/:friendlyUrl/tags/:tag/:value', 91 | component: Artifact 92 | }, 93 | { 94 | path: '/items/:friendlyUrl/pageno/:pageno', 95 | component: Artifact 96 | }, 97 | { 98 | path: '/items/:friendlyUrl/:pageUrl', 99 | component: ArtifactItem 100 | }, 101 | { 102 | path: '/tags/:friendlyUrl', 103 | component: Tag 104 | }, 105 | { 106 | path: '/tags/:friendlyUrl/:valueUrl', 107 | component: TagValue 108 | }, 109 | { 110 | path: '/search', 111 | component: Search 112 | }, 113 | { 114 | path: '/ganjoor', 115 | component: GanjoorFrame 116 | }, 117 | { 118 | path: '/glinkrev', 119 | component: GanjoorLinks 120 | }, 121 | { 122 | path: '/notifications', 123 | component: Notifications 124 | }, 125 | { 126 | path: '/logs', 127 | component: Events 128 | }, 129 | { 130 | path: '/plinkrev', 131 | component: PinterestLinks 132 | }, 133 | { 134 | path: '/utils', 135 | component: MixUtils 136 | }, 137 | { 138 | path: '/reported', 139 | component: ReportedNotes 140 | }, 141 | ] -------------------------------------------------------------------------------- /src/components/MixUtils.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 115 | 116 | -------------------------------------------------------------------------------- /src/plugins/tracking.js: -------------------------------------------------------------------------------- 1 | export default { 2 | install(Vue, options = {}) { 3 | const config = { 4 | siteId: options.id || "1", 5 | defaultStatus: options.status || "active", 6 | debug: options.debug || false, 7 | titleCheckMaxWait: 2000, 8 | titleCheckInterval: 100 9 | }; 10 | 11 | const log = (...args) => config.debug && console.log('[Tracker]', ...args); 12 | 13 | const initializeTracking = () => { 14 | if (window.kntrTracking) return; 15 | 16 | window.kntrTracking = { 17 | getOrCreateCookie: function (cookieName, isSessionCookie = false) { 18 | let cookieValue = this.getCookie(cookieName); 19 | if (!cookieValue) { 20 | cookieValue = this.generateUniqueId(); 21 | let cookieSettings = `path=/; SameSite=None; Secure;`; 22 | if (!isSessionCookie) { 23 | const expirationDate = new Date(); 24 | expirationDate.setFullYear(expirationDate.getFullYear() + 1); 25 | cookieSettings += `expires=${expirationDate.toUTCString()};`; 26 | } 27 | document.cookie = `${cookieName}=${cookieValue}; ${cookieSettings}`; 28 | } 29 | return cookieValue; 30 | }, 31 | 32 | getCookie: function (name) { 33 | const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); 34 | return match ? match[2] : null; 35 | }, 36 | 37 | generateUniqueId: function () { 38 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 39 | const r = Math.random() * 16 | 0; 40 | const v = c === 'x' ? r : (r & 0x3 | 0x8); 41 | return v.toString(16); 42 | }); 43 | }, 44 | 45 | startTracking: function (trackingId, siteSpecificUserHash = "") { // Default empty string 46 | const trackingApiUrl = "https://track.kntr.ir/tracking/" + trackingId; 47 | const data = { 48 | url: window.location.href, 49 | referrer: document.referrer, 50 | title: document.title, 51 | platform: navigator.platform, 52 | screenWidth: window.screen.width, 53 | screenHeight: window.screen.height, 54 | viewPortWidth: window.innerWidth, 55 | viewPortHeight: window.innerHeight, 56 | timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, 57 | siteSpecificUserHash: siteSpecificUserHash, // Will be empty string if not provided 58 | userUniqueId: this.getOrCreateCookie("KontorUserUniqueId"), 59 | sessionUniqueId: this.getOrCreateCookie("KontorSessionUniqueId", true) 60 | }; 61 | 62 | fetch(trackingApiUrl, { 63 | method: "POST", 64 | headers: { "Content-Type": "application/json" }, 65 | body: JSON.stringify(data), 66 | credentials: "include" 67 | }).catch(error => { 68 | log('Tracking error:', error); 69 | }); 70 | } 71 | }; 72 | }; 73 | 74 | const trackWithTitleCheck = (status, initialTitle = null) => { 75 | const startTime = Date.now(); 76 | const currentTitle = initialTitle || document.title; 77 | 78 | if (initialTitle === null && /[\u0600-\u06FF]/.test(currentTitle)) { 79 | window.kntrTracking.startTracking(config.siteId, ""); // Explicit empty string 80 | log('Tracked (initial):', status, 'Title:', currentTitle); 81 | return; 82 | } 83 | 84 | const checkTitle = () => { 85 | const elapsed = Date.now() - startTime; 86 | const newTitle = document.title; 87 | 88 | if (newTitle !== currentTitle || elapsed > config.titleCheckMaxWait) { 89 | window.kntrTracking.startTracking(config.siteId, ""); // Explicit empty string 90 | log('Tracked (after', elapsed, 'ms):', status, 'Title:', newTitle); 91 | } else { 92 | setTimeout(checkTitle, config.titleCheckInterval); 93 | } 94 | }; 95 | 96 | checkTitle(); 97 | }; 98 | 99 | // Initialization 100 | initializeTracking(); 101 | trackWithTitleCheck('initial_load', document.title); 102 | 103 | if (options.router) { 104 | options.router.afterEach((to) => { 105 | trackWithTitleCheck(`route:${to.path}`); 106 | }); 107 | } 108 | } 109 | }; -------------------------------------------------------------------------------- /src/components/TagValue.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 102 | 103 | -------------------------------------------------------------------------------- /src/components/ZoomOnHover.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 108 | 109 | -------------------------------------------------------------------------------- /src/components/GanjoorLinks.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 118 | 119 | -------------------------------------------------------------------------------- /src/components/Events.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 179 | 180 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 110 | 111 | 121 | 122 | 177 | 178 | 193 | -------------------------------------------------------------------------------- /src/components/Items.vue: -------------------------------------------------------------------------------- 1 | 71 | 180 | -------------------------------------------------------------------------------- /src/components/PinterestLinks.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 137 | 138 | -------------------------------------------------------------------------------- /src/components/UserNotes.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 142 | 143 | -------------------------------------------------------------------------------- /src/components/Bookmarks.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 148 | 149 | -------------------------------------------------------------------------------- /src/components/AllPublicNotes.vue: -------------------------------------------------------------------------------- 1 | 89 | 90 | 149 | 150 | -------------------------------------------------------------------------------- /src/components/ReportedNotes.vue: -------------------------------------------------------------------------------- 1 | 111 | 112 | 232 | 233 | -------------------------------------------------------------------------------- /src/components/Notifications.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 195 | 196 | -------------------------------------------------------------------------------- /src/components/Profile.vue: -------------------------------------------------------------------------------- 1 | 97 | 98 | 247 | 248 | -------------------------------------------------------------------------------- /src/components/Search.vue: -------------------------------------------------------------------------------- 1 | 127 | 128 | 255 | 256 | -------------------------------------------------------------------------------- /src/components/Roles.vue: -------------------------------------------------------------------------------- 1 | 61 | 62 | 222 | 223 | -------------------------------------------------------------------------------- /src/components/ForgotPassword.vue: -------------------------------------------------------------------------------- 1 | 101 | 102 | 292 | 293 | 298 | -------------------------------------------------------------------------------- /src/components/HomePage.vue: -------------------------------------------------------------------------------- 1 | 119 | 237 | -------------------------------------------------------------------------------- /src/components/Users.vue: -------------------------------------------------------------------------------- 1 | 119 | 120 | 388 | 389 | -------------------------------------------------------------------------------- /src/components/UserSidebarWidget.vue: -------------------------------------------------------------------------------- 1 | 230 | 231 | 382 | 383 | 415 | -------------------------------------------------------------------------------- /src/components/SignUp.vue: -------------------------------------------------------------------------------- 1 | 212 | 213 | 451 | 452 | 457 | --------------------------------------------------------------------------------