├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── .gitmodules ├── README.md ├── assets ├── capture_individual.png ├── capture_interactive-tree.png ├── capture_tree-home.png ├── individual.png ├── interactive-tree.png └── tree-home.png ├── babel.config.js ├── composer.json ├── composer.lock ├── module.php ├── package-lock.json ├── package.json ├── postcss.config.js ├── resources ├── css │ ├── theme.css │ └── vendor.css ├── js │ ├── theme.js │ └── vendor.js └── views │ ├── calendar-list.phtml │ ├── calendar-page.phtml │ ├── chart-box.phtml │ ├── individual-page-images.phtml │ ├── individual-page-tabs.phtml │ ├── layouts │ └── default.phtml │ ├── lists │ ├── notes-table.phtml │ ├── repositories-table.phtml │ ├── sources-table.phtml │ └── surnames-table.phtml │ ├── modules │ ├── contact-links │ │ └── footer.phtml │ ├── descendancy │ │ └── sidebar.phtml │ ├── faq │ │ └── show.phtml │ ├── gedcom_stats │ │ └── statistics.phtml │ ├── hit-counter │ │ └── footer.phtml │ ├── interactive-tree │ │ └── chart.phtml │ ├── lifespans-chart │ │ └── chart.phtml │ ├── lightbox │ │ └── tab.phtml │ ├── media-list │ │ └── page.phtml │ ├── pedigree-map │ │ └── chart.phtml │ ├── place-hierarchy │ │ ├── list.phtml │ │ ├── map.phtml │ │ ├── page.phtml │ │ ├── popup.phtml │ │ └── sidebar.phtml │ ├── places │ │ └── tab.phtml │ ├── powered-by-webtrees │ │ └── footer.phtml │ ├── privacy-policy │ │ └── footer.phtml │ ├── recent_changes │ │ └── changes-list.phtml │ ├── relatives │ │ └── family.phtml │ ├── statistics-chart │ │ └── page.phtml │ ├── stories │ │ └── tab.phtml │ └── todo │ │ └── research-tasks.phtml │ └── place-hierarchy.phtml ├── src ├── js │ ├── theme.js │ └── vendor.js └── scss │ ├── _forms.scss │ ├── _icons.scss │ ├── _tables.scss │ └── theme.scss └── webpack.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | # Browsers that we support 2 | 3 | defaults 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: [ 7 | 'airbnb-base', 8 | ], 9 | parserOptions: { 10 | ecmaVersion: 'latest', 11 | sourceType: 'module', 12 | }, 13 | rules: { 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directories 2 | node_modules/ 3 | vendor/ 4 | 5 | # Sass 6 | .sass-cache/ 7 | *.css.map 8 | *.sass.map 9 | *.scss.map 10 | 11 | # Dev 12 | dev/ 13 | 14 | # Build 15 | dist/ 16 | 17 | # Misc 18 | .DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/scss/argon-dashboard"] 2 | path = src/scss/argon-dashboard 3 | url = git@github.com:creativetimofficial/argon-dashboard.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](https://github.com/jchue/argon-webtrees-theme/releases/latest) 2 | [](https://webtrees.net/download) 3 | 4 | # Argon Theme for webtrees 5 | 6 | A theme for the [webtrees](https://github.com/fisharebest/webtrees) online geneology application based on the [Argon Dashboard](https://github.com/creativetimofficial/argon-dashboard). Since webtrees is templated with Bootstrap, this theme applies Argon styles in the majority of places but adapts where necessary. 7 | 8 | ## Screenshots 9 | 10 | **Tree Home** 11 | 12 |  13 | 14 | **Individual Page** 15 | 16 |  17 | 18 | **Interactive Tree Chart** 19 | 20 |  21 | 22 | ## Compatibility 23 | 24 | webtrees 2.1.x (see [prior releases](https://github.com/jchue/argon-webtrees-theme/releases) for older versions) 25 | 26 | ## Installation 27 | 28 | 1. Download the .zip file of the [latest release](https://github.com/jchue/argon-webtrees-theme/releases/latest). 29 | 2. Unzip the package. 30 | 3. Ensure the folder is named `argon`. 31 | 4. Upload the folder into the `modules_v4` directory of the webtrees installation on your web server. 32 | 5. Ensure the theme is enabled in your Control panel. 33 | 34 | ## Structure 35 | 36 | Because webtrees 2 is built with Bootstrap by default, the majority of this theme is just a matter of applying the Argon stylesheet. 37 | 38 | Additionally, there are a handful of opinionated changes, mostly regarding sizing and spacing, requiring some views to be overwritten. Most of these are achieved with a simple replacement function to add/remove/modify classes and elements. Therefore, when a change is introduced in the webtrees codebase, these views should adopt them accordingly unless there is a drastic change to the template. 39 | 40 | There are, however, a few cases that require the entire view to be rebuilt/reorganized, due to either a completely different template or a change in the PHP code. These views are: 41 | 42 | - `::layouts/default` 43 | - `::modules/faq/show` 44 | - `::modules/lifespans-chart/chart` 45 | - `::modules/recent_changes/changes-list` 46 | - `::modules/stories/tab` 47 | 48 | When change is made to these views in the webtrees codebase, it needs to be incorporated in the corresponding Argon view. 49 | 50 | ## Develop and Build 51 | 52 | **Prerequisites:** 53 | 54 | - Node.js 55 | - webtrees 56 | 57 | **Clone repository** 58 | 59 | `argon-dashboard` must be sourced as a Git submodules. 60 | 61 | Therefore, you must pass the `--recurse-submodules` flag when cloning the repository in order for its contents to be populated (under `src/resources/scss/argon-dashboard`): 62 | 63 | ``` 64 | git clone --recurse-submodules git@github.com:jchue/argon-webtrees-theme.git 65 | ``` 66 | 67 | **Install dependencies and run in watch mode** 68 | 69 | webtrees itself is a required dependency, since its base and vendor styles are utilized in the pipeline. First install it as well as its subdependencies: 70 | 71 | ```sh 72 | composer install 73 | npm run vendor 74 | ``` 75 | 76 | Composer is configured to install webtrees from source, so it should include the required stylesheets. 77 | 78 | Then install the theme's Node dependencies and start the webpack watcher: 79 | 80 | ```sh 81 | npm install 82 | npm run dev 83 | ``` 84 | 85 | To support Sass and ECMAScript, the stylesheets and scripts are developed in their respective directories under `src/`. When a change is detected, they are compiled/transpiled to `resources/`, from which webtrees serves the theme. The PHP views themselves are housed directly under the `resources/` directory already. 86 | 87 | **Build and package** 88 | 89 | ```sh 90 | npm run build 91 | ``` 92 | 93 | This will compile/transpile the stylsheets/scripts and package them, along with the PHP views, in a `dist/` directory. -------------------------------------------------------------------------------- /assets/capture_individual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jchue/argon-webtrees-theme/f266909a3a668f2dff799240a87dd749a251fb94/assets/capture_individual.png -------------------------------------------------------------------------------- /assets/capture_interactive-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jchue/argon-webtrees-theme/f266909a3a668f2dff799240a87dd749a251fb94/assets/capture_interactive-tree.png -------------------------------------------------------------------------------- /assets/capture_tree-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jchue/argon-webtrees-theme/f266909a3a668f2dff799240a87dd749a251fb94/assets/capture_tree-home.png -------------------------------------------------------------------------------- /assets/individual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jchue/argon-webtrees-theme/f266909a3a668f2dff799240a87dd749a251fb94/assets/individual.png -------------------------------------------------------------------------------- /assets/interactive-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jchue/argon-webtrees-theme/f266909a3a668f2dff799240a87dd749a251fb94/assets/interactive-tree.png -------------------------------------------------------------------------------- /assets/tree-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jchue/argon-webtrees-theme/f266909a3a668f2dff799240a87dd749a251fb94/assets/tree-home.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@babel/preset-env'], 3 | }; 4 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "preferred-install": { 4 | "fisharebest/webtrees": "source" 5 | } 6 | }, 7 | "require-dev": { 8 | "fisharebest/webtrees": "~2.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /module.php: -------------------------------------------------------------------------------- 1 | 'fff4f9', 37 | 'chart-background-m' => 'f4fdff', 38 | 'chart-background-u' => 'f4f5f7', 39 | 'chart-box-x' => 260, 40 | 'chart-box-y' => 85, 41 | 'chart-font-color' => '000000', 42 | 'chart-spacing-x' => 5, 43 | 'chart-spacing-y' => 10, 44 | 'compact-chart-box-x' => 240, 45 | 'compact-chart-box-y' => 50, 46 | 'distribution-chart-high-values' => '84beff', 47 | 'distribution-chart-low-values' => 'c3dfff', 48 | 'distribution-chart-no-values' => 'ffffff', 49 | ]; 50 | 51 | return $parameters[$parameter_name]; 52 | } 53 | 54 | /** 55 | * Bootstrap the module 56 | */ 57 | public function boot(): void 58 | { 59 | // Register a namespace for our views. 60 | View::registerNamespace($this->name(), $this->resourcesFolder() . 'views/'); 61 | 62 | // Replace an existing views with our own versions. 63 | 64 | /** 65 | * Global 66 | */ 67 | View::registerCustomView('::layouts/default', $this->name() . '::layouts/default'); // Site template 68 | View::registerCustomView('::modules/contact-links/footer', $this->name() . '::modules/contact-links/footer'); // Footer > contact line 69 | View::registerCustomView('::modules/hit-counter/footer', $this->name() . '::modules/hit-counter/footer'); // Footer > view count 70 | View::registerCustomView('::modules/powered-by-webtrees/footer', $this->name() . '::modules/powered-by-webtrees/footer'); // Footer > webtrees link 71 | View::registerCustomView('::modules/privacy-policy/footer', $this->name() . '::modules/privacy-policy/footer'); // Footer > privacy policy link 72 | 73 | /** 74 | * Tree Page Blocks 75 | */ 76 | View::registerCustomView('::modules/gedcom_stats/statistics', $this->name() . '::modules/gedcom_stats/statistics'); // Blocks > Statistics 77 | View::registerCustomView('::modules/todo/research-tasks', $this->name() . '::modules/todo/research-tasks'); // Blocks > Research tasks 78 | View::registerCustomView('::modules/recent_changes/changes-list', $this->name() . '::modules/recent_changes/changes-list'); // Blocks > Recent changes (list layout) 79 | 80 | /** 81 | * Individual Page 82 | */ 83 | View::registerCustomView('::individual-page-images', $this->name() . '::individual-page-images'); // Individual page thumbnails 84 | View::registerCustomView('::individual-page-tabs', $this->name() . '::individual-page-tabs'); // Individual page tabs 85 | View::registerCustomView('::modules/relatives/family', $this->name() . '::modules/relatives/family'); // Individual > Families tab 86 | View::registerCustomView('::modules/stories/tab', $this->name() . '::modules/stories/tab'); // Individual > Stories tab 87 | View::registerCustomView('::modules/lightbox/tab', $this->name() . '::modules/lightbox/tab'); // Individual > Album tab 88 | View::registerCustomView('::modules/places/tab', $this->name() . '::modules/places/tab'); // Individual > Places tab 89 | View::registerCustomView('::modules/descendancy/sidebar', $this->name() . '::modules/descendancy/sidebar'); // Individual > Descendants sidebar 90 | 91 | /** 92 | * Charts 93 | */ 94 | View::registerCustomView('::modules/interactive-tree/chart', $this->name() . '::modules/interactive-tree/chart'); // Charts > Interactive tree AND Individual > Interactive tree tab 95 | View::registerCustomView('::chart-box', $this->name() . '::chart-box'); // Individuals' boxes in Charts > Ancestors, Compact Tree, Descendants, Family Book, Hourglass Chart, Pedigree, Relationships 96 | View::registerCustomView('::modules/lifespans-chart/chart', $this->name() . '::modules/lifespans-chart/chart'); // Charts > Lifespans 97 | View::registerCustomView('::modules/pedigree-map/chart', $this->name() . '::modules/pedigree-map/chart'); // Charts > Pedigree map 98 | View::registerCustomView('::modules/statistics-chart/page', $this->name() . '::modules/statistics-chart/page'); // Charts > Statistics 99 | 100 | /** 101 | * FAQ Page 102 | */ 103 | View::registerCustomView('::modules/faq/show', $this->name() . '::modules/faq/show'); // Page template 104 | 105 | /** 106 | * Lists 107 | */ 108 | View::registerCustomView('::lists/surnames-table', $this->name() . '::lists/surnames-table'); // Lists > Families AND Lists > Individuals 109 | View::registerCustomView('::modules/media-list/page', $this->name() . '::modules/media-list/page'); // Lists > Media objects 110 | View::registerCustomView('::modules/place-hierarchy/page', $this->name() . '::modules/place-hierarchy/page'); // Lists > Place hierarchy page 111 | View::registerCustomView('::place-hierarchy', $this->name() . '::place-hierarchy'); // Lists > Place hierarchy page > Place hierarchy (without map) 112 | View::registerCustomView('::modules/place-hierarchy/map', $this->name() . '::modules/place-hierarchy/map'); // Lists > Place hierarchy page > map 113 | View::registerCustomView('::modules/place-hierarchy/sidebar', $this->name() . '::modules/place-hierarchy/sidebar'); // Lists > Place hierarchy page > location entries 114 | View::registerCustomView('::modules/place-hierarchy/popup', $this->name() . '::modules/place-hierarchy/popup'); // Lists > Place hierarchy page > map pin popup 115 | View::registerCustomView('::modules/place-hierarchy/list', $this->name() . '::modules/place-hierarchy/list'); // Lists > Place hierarchy page > Place list (under map) 116 | View::registerCustomView('::lists/repositories-table', $this->name() . '::lists/repositories-table'); // Lists > Repositories 117 | View::registerCustomView('::lists/notes-table', $this->name() . '::lists/notes-table'); // Lists > Shared notes 118 | View::registerCustomView('::lists/sources-table', $this->name() . '::lists/sources-table'); // Lists > Sources 119 | 120 | /** 121 | * Calendar 122 | */ 123 | View::registerCustomView('::calendar-page', $this->name() . '::calendar-page'); // Calendar > Day/Month/Year > "View" row 124 | View::registerCustomView('::calendar-list', $this->name() . '::calendar-list'); // Calendar > Day > individuals/families table 125 | } 126 | 127 | /** 128 | * Where does this module store its resources 129 | * 130 | * @return string 131 | */ 132 | public function resourcesFolder(): string 133 | { 134 | return __DIR__ . '/resources/'; 135 | } 136 | 137 | /** 138 | * Replace Minimal spreadsheet with Argon spreadsheet 139 | * 140 | * @return array 141 | */ 142 | public function stylesheets(): array 143 | { 144 | // NOTE - a future version of webtrees will allow the modules to be stored in a private folder. 145 | // Only files in the /public/ folder will be accessible via the webserver. 146 | // Since modules cannot copy their files to the /public/ folder, they need to provide them via a callback. 147 | $stylesheets[] = $this->assetUrl('css/vendor.css'); 148 | $stylesheets[] = $this->assetUrl('css/theme.css'); 149 | 150 | return $stylesheets; 151 | } 152 | 153 | /** 154 | * Raw content, to be added at the end of the
element. 155 | * Typically, this will be '; 162 | 163 | return $bodyContent; 164 | } 165 | }; 166 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "vendor": "cd vendor/fisharebest/webtrees && npm install", 5 | "lint": "eslint src/js/", 6 | "dev": "webpack --watch", 7 | "build": "rm -r dist && npm run vendor && npm run lint && webpack --node-env production" 8 | }, 9 | "devDependencies": { 10 | "@babel/core": "^7.21.0", 11 | "@babel/preset-env": "^7.20.2", 12 | "@fortawesome/fontawesome-free": "^6.3.0", 13 | "autoprefixer": "^10.4.13", 14 | "babel-loader": "^9.1.2", 15 | "copy-webpack-plugin": "^11.0.0", 16 | "css-loader": "^6.7.3", 17 | "cssnano": "^5.1.15", 18 | "eslint": "^8.35.0", 19 | "eslint-config-airbnb-base": "^15.0.0", 20 | "eslint-plugin-import": "^2.27.5", 21 | "filemanager-webpack-plugin": "^8.0.0", 22 | "mini-css-extract-plugin": "^2.7.2", 23 | "postcss": "^8.4.21", 24 | "postcss-import": "^14.1.0", 25 | "postcss-loader": "^7.0.2", 26 | "postcss-url": "^10.1.3", 27 | "sass": "^1.58.3", 28 | "sass-loader": "^13.2.0", 29 | "webpack": "^5.75.0", 30 | "webpack-cli": "^5.0.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | const path = require('node:path'); 2 | 3 | module.exports = (ctx) => ({ 4 | map: false, 5 | plugins: { 6 | autoprefixer: ctx.env === 'production' ? {} : false, 7 | cssnano: ctx.env === 'production' ? { 8 | preset: ['default', { 9 | discardComments: { 10 | removeAll: true, 11 | }, 12 | }], 13 | } : false, 14 | 'postcss-import': { 15 | path: [ 16 | 'vendor/fisharebest/webtrees/resources/css', 17 | 'src/scss', 18 | ], 19 | }, 20 | 21 | /** 22 | * TODO: Reconsider inlining font faces and instead defining them on page; 23 | * would need to figure out how to exclude fontawesome.css from PostCSS processing 24 | */ 25 | 'postcss-url': { 26 | url: 'inline', 27 | basePath: [ 28 | path.resolve('node_modules/@fortawesome/fontawesome-free/webfonts'), 29 | path.resolve('vendor/fisharebest/webtrees/resources/css'), 30 | ], 31 | }, 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /resources/js/theme.js: -------------------------------------------------------------------------------- 1 | /******/ (function() { // webpackBootstrap 2 | /******/ "use strict"; 3 | /******/ var __webpack_modules__ = ({ 4 | 5 | /***/ "./src/scss/theme.scss": 6 | /*!*****************************!*\ 7 | !*** ./src/scss/theme.scss ***! 8 | \*****************************/ 9 | /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 10 | 11 | __webpack_require__.r(__webpack_exports__); 12 | // extracted by mini-css-extract-plugin 13 | 14 | 15 | /***/ }) 16 | 17 | /******/ }); 18 | /************************************************************************/ 19 | /******/ // The module cache 20 | /******/ var __webpack_module_cache__ = {}; 21 | /******/ 22 | /******/ // The require function 23 | /******/ function __webpack_require__(moduleId) { 24 | /******/ // Check if module is in cache 25 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 26 | /******/ if (cachedModule !== undefined) { 27 | /******/ return cachedModule.exports; 28 | /******/ } 29 | /******/ // Create a new module (and put it into the cache) 30 | /******/ var module = __webpack_module_cache__[moduleId] = { 31 | /******/ // no module.id needed 32 | /******/ // no module.loaded needed 33 | /******/ exports: {} 34 | /******/ }; 35 | /******/ 36 | /******/ // Execute the module function 37 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 38 | /******/ 39 | /******/ // Return the exports of the module 40 | /******/ return module.exports; 41 | /******/ } 42 | /******/ 43 | /************************************************************************/ 44 | /******/ /* webpack/runtime/make namespace object */ 45 | /******/ !function() { 46 | /******/ // define __esModule on exports 47 | /******/ __webpack_require__.r = function(exports) { 48 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 49 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 50 | /******/ } 51 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 52 | /******/ }; 53 | /******/ }(); 54 | /******/ 55 | /************************************************************************/ 56 | var __webpack_exports__ = {}; 57 | // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. 58 | !function() { 59 | /*!*************************!*\ 60 | !*** ./src/js/theme.js ***! 61 | \*************************/ 62 | __webpack_require__.r(__webpack_exports__); 63 | /* harmony import */ var _scss_theme_scss__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../scss/theme.scss */ "./src/scss/theme.scss"); 64 | // Need to import stylesheet so Webpack processes it 65 | 66 | const secondaryHeader = document.getElementById('secondary-header'); 67 | const secondaryHeaderHeight = secondaryHeader.offsetHeight; 68 | const primaryHeader = document.getElementById('primary-header'); 69 | const primaryHeaderHeight = primaryHeader.offsetHeight; 70 | const siteContent = document.getElementById('content'); 71 | function setHeader() { 72 | const scrollPosition = document.documentElement.scrollTop || document.body.scrollTop; 73 | if (scrollPosition > secondaryHeaderHeight) { 74 | primaryHeader.style.position = 'fixed'; 75 | siteContent.style.marginTop = `${primaryHeaderHeight}px`; 76 | } else { 77 | primaryHeader.style.position = 'static'; 78 | siteContent.style.marginTop = 0; 79 | } 80 | } 81 | window.addEventListener('load', setHeader); 82 | window.addEventListener('scroll', setHeader); 83 | }(); 84 | /******/ })() 85 | ; 86 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianMvdGhlbWUuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTs7Ozs7OztVQ0FBO1VBQ0E7O1VBRUE7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7O1VBRUE7VUFDQTs7VUFFQTtVQUNBO1VBQ0E7Ozs7O1dDdEJBO1dBQ0E7V0FDQTtXQUNBLHVEQUF1RCxpQkFBaUI7V0FDeEU7V0FDQSxnREFBZ0QsYUFBYTtXQUM3RDs7Ozs7Ozs7Ozs7O0FDTkE7QUFDNEI7QUFFNUIsTUFBTUEsZUFBZSxHQUFHQyxRQUFRLENBQUNDLGNBQWMsQ0FBQyxrQkFBa0IsQ0FBQztBQUNuRSxNQUFNQyxxQkFBcUIsR0FBR0gsZUFBZSxDQUFDSSxZQUFZO0FBRTFELE1BQU1DLGFBQWEsR0FBR0osUUFBUSxDQUFDQyxjQUFjLENBQUMsZ0JBQWdCLENBQUM7QUFDL0QsTUFBTUksbUJBQW1CLEdBQUdELGFBQWEsQ0FBQ0QsWUFBWTtBQUV0RCxNQUFNRyxXQUFXLEdBQUdOLFFBQVEsQ0FBQ0MsY0FBYyxDQUFDLFNBQVMsQ0FBQztBQUV0RCxTQUFTTSxTQUFTQSxDQUFBLEVBQUc7RUFDbkIsTUFBTUMsY0FBYyxHQUFHUixRQUFRLENBQUNTLGVBQWUsQ0FBQ0MsU0FBUyxJQUFJVixRQUFRLENBQUNXLElBQUksQ0FBQ0QsU0FBUztFQUVwRixJQUFJRixjQUFjLEdBQUdOLHFCQUFxQixFQUFFO0lBQzFDRSxhQUFhLENBQUNRLEtBQUssQ0FBQ0MsUUFBUSxHQUFHLE9BQU87SUFDdENQLFdBQVcsQ0FBQ00sS0FBSyxDQUFDRSxTQUFTLEdBQUksR0FBRVQsbUJBQW9CLElBQUc7RUFDMUQsQ0FBQyxNQUFNO0lBQ0xELGFBQWEsQ0FBQ1EsS0FBSyxDQUFDQyxRQUFRLEdBQUcsUUFBUTtJQUN2Q1AsV0FBVyxDQUFDTSxLQUFLLENBQUNFLFNBQVMsR0FBRyxDQUFDO0VBQ2pDO0FBQ0Y7QUFFQUMsTUFBTSxDQUFDQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUVULFNBQVMsQ0FBQztBQUMxQ1EsTUFBTSxDQUFDQyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUVULFNBQVMsQ0FBQyxDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL3Njc3MvdGhlbWUuc2Nzcz9kOTViIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly8vd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly8vLi9zcmMvanMvdGhlbWUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gZXh0cmFjdGVkIGJ5IG1pbmktY3NzLWV4dHJhY3QtcGx1Z2luXG5leHBvcnQge307IiwiLy8gVGhlIG1vZHVsZSBjYWNoZVxudmFyIF9fd2VicGFja19tb2R1bGVfY2FjaGVfXyA9IHt9O1xuXG4vLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcblx0dmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07XG5cdGlmIChjYWNoZWRNb2R1bGUgIT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiBjYWNoZWRNb2R1bGUuZXhwb3J0cztcblx0fVxuXHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuXHR2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHtcblx0XHQvLyBubyBtb2R1bGUuaWQgbmVlZGVkXG5cdFx0Ly8gbm8gbW9kdWxlLmxvYWRlZCBuZWVkZWRcblx0XHRleHBvcnRzOiB7fVxuXHR9O1xuXG5cdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuXHRfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXShtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuXHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG59XG5cbiIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiLy8gTmVlZCB0byBpbXBvcnQgc3R5bGVzaGVldCBzbyBXZWJwYWNrIHByb2Nlc3NlcyBpdFxuaW1wb3J0ICcuLi9zY3NzL3RoZW1lLnNjc3MnO1xuXG5jb25zdCBzZWNvbmRhcnlIZWFkZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2Vjb25kYXJ5LWhlYWRlcicpO1xuY29uc3Qgc2Vjb25kYXJ5SGVhZGVySGVpZ2h0ID0gc2Vjb25kYXJ5SGVhZGVyLm9mZnNldEhlaWdodDtcblxuY29uc3QgcHJpbWFyeUhlYWRlciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwcmltYXJ5LWhlYWRlcicpO1xuY29uc3QgcHJpbWFyeUhlYWRlckhlaWdodCA9IHByaW1hcnlIZWFkZXIub2Zmc2V0SGVpZ2h0O1xuXG5jb25zdCBzaXRlQ29udGVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjb250ZW50Jyk7XG5cbmZ1bmN0aW9uIHNldEhlYWRlcigpIHtcbiAgY29uc3Qgc2Nyb2xsUG9zaXRpb24gPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wO1xuXG4gIGlmIChzY3JvbGxQb3NpdGlvbiA+IHNlY29uZGFyeUhlYWRlckhlaWdodCkge1xuICAgIHByaW1hcnlIZWFkZXIuc3R5bGUucG9zaXRpb24gPSAnZml4ZWQnO1xuICAgIHNpdGVDb250ZW50LnN0eWxlLm1hcmdpblRvcCA9IGAke3ByaW1hcnlIZWFkZXJIZWlnaHR9cHhgO1xuICB9IGVsc2Uge1xuICAgIHByaW1hcnlIZWFkZXIuc3R5bGUucG9zaXRpb24gPSAnc3RhdGljJztcbiAgICBzaXRlQ29udGVudC5zdHlsZS5tYXJnaW5Ub3AgPSAwO1xuICB9XG59XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgc2V0SGVhZGVyKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzZXRIZWFkZXIpO1xuIl0sIm5hbWVzIjpbInNlY29uZGFyeUhlYWRlciIsImRvY3VtZW50IiwiZ2V0RWxlbWVudEJ5SWQiLCJzZWNvbmRhcnlIZWFkZXJIZWlnaHQiLCJvZmZzZXRIZWlnaHQiLCJwcmltYXJ5SGVhZGVyIiwicHJpbWFyeUhlYWRlckhlaWdodCIsInNpdGVDb250ZW50Iiwic2V0SGVhZGVyIiwic2Nyb2xsUG9zaXRpb24iLCJkb2N1bWVudEVsZW1lbnQiLCJzY3JvbGxUb3AiLCJib2R5Iiwic3R5bGUiLCJwb3NpdGlvbiIsIm1hcmdpblRvcCIsIndpbmRvdyIsImFkZEV2ZW50TGlzdGVuZXIiXSwic291cmNlUm9vdCI6IiJ9 -------------------------------------------------------------------------------- /resources/js/vendor.js: -------------------------------------------------------------------------------- 1 | /******/ (function() { // webpackBootstrap 2 | /******/ "use strict"; 3 | /******/ var __webpack_modules__ = ({ 4 | 5 | /***/ "./vendor/fisharebest/webtrees/resources/css/vendor.tmp.css": 6 | /*!******************************************************************!*\ 7 | !*** ./vendor/fisharebest/webtrees/resources/css/vendor.tmp.css ***! 8 | \******************************************************************/ 9 | /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 10 | 11 | __webpack_require__.r(__webpack_exports__); 12 | // extracted by mini-css-extract-plugin 13 | 14 | 15 | /***/ }) 16 | 17 | /******/ }); 18 | /************************************************************************/ 19 | /******/ // The module cache 20 | /******/ var __webpack_module_cache__ = {}; 21 | /******/ 22 | /******/ // The require function 23 | /******/ function __webpack_require__(moduleId) { 24 | /******/ // Check if module is in cache 25 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 26 | /******/ if (cachedModule !== undefined) { 27 | /******/ return cachedModule.exports; 28 | /******/ } 29 | /******/ // Create a new module (and put it into the cache) 30 | /******/ var module = __webpack_module_cache__[moduleId] = { 31 | /******/ // no module.id needed 32 | /******/ // no module.loaded needed 33 | /******/ exports: {} 34 | /******/ }; 35 | /******/ 36 | /******/ // Execute the module function 37 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 38 | /******/ 39 | /******/ // Return the exports of the module 40 | /******/ return module.exports; 41 | /******/ } 42 | /******/ 43 | /************************************************************************/ 44 | /******/ /* webpack/runtime/make namespace object */ 45 | /******/ !function() { 46 | /******/ // define __esModule on exports 47 | /******/ __webpack_require__.r = function(exports) { 48 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 49 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 50 | /******/ } 51 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 52 | /******/ }; 53 | /******/ }(); 54 | /******/ 55 | /************************************************************************/ 56 | var __webpack_exports__ = {}; 57 | // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. 58 | !function() { 59 | /*!**************************!*\ 60 | !*** ./src/js/vendor.js ***! 61 | \**************************/ 62 | __webpack_require__.r(__webpack_exports__); 63 | /* harmony import */ var _vendor_fisharebest_webtrees_resources_css_vendor_tmp_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../vendor/fisharebest/webtrees/resources/css/vendor.tmp.css */ "./vendor/fisharebest/webtrees/resources/css/vendor.tmp.css"); 64 | // Need to import stylesheet so Webpack processes it 65 | 66 | }(); 67 | /******/ })() 68 | ; 69 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianMvdmVuZG9yLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBQUE7Ozs7Ozs7VUNBQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBOztVQUVBO1VBQ0E7O1VBRUE7VUFDQTtVQUNBOzs7OztXQ3RCQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7Ozs7OztBQ05BIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vdmVuZG9yL2Zpc2hhcmViZXN0L3dlYnRyZWVzL3Jlc291cmNlcy9jc3MvdmVuZG9yLnRtcC5jc3M/OWNkZCIsIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vLy4vc3JjL2pzL3ZlbmRvci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBleHRyYWN0ZWQgYnkgbWluaS1jc3MtZXh0cmFjdC1wbHVnaW5cbmV4cG9ydCB7fTsiLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG5cdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xuXHRcdC8vIG5vIG1vZHVsZS5pZCBuZWVkZWRcblx0XHQvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZFxuXHRcdGV4cG9ydHM6IHt9XG5cdH07XG5cblx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG5cdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdKG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG5cdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG5cdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbn1cblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCIvLyBOZWVkIHRvIGltcG9ydCBzdHlsZXNoZWV0IHNvIFdlYnBhY2sgcHJvY2Vzc2VzIGl0XG5pbXBvcnQgJy4uLy4uL3ZlbmRvci9maXNoYXJlYmVzdC93ZWJ0cmVlcy9yZXNvdXJjZXMvY3NzL3ZlbmRvci50bXAuY3NzJztcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== -------------------------------------------------------------------------------- /resources/views/calendar-list.phtml: -------------------------------------------------------------------------------- 1 | (\r\n|\r|\n|\s)+21 | = $subtitle ?> 22 |
23 | 24 |