{"version":3,"file":"store-C1O4TdnV.js","sources":["../../../node_modules/@experiments-labs/rise_ui/src/components/DataDisplay/ImageViewer/ImageViewer.vue","../../../node_modules/@experiments-labs/rise_ui/src/components/Modal/Modal.vue","../../../node_modules/@experiments-labs/rise_ui/src/components/Modal/ConfirmDialog.vue","../../../node_modules/@experiments-labs/rise_ui/src/components/DataDisplay/Thumbnails/Thumbnails.vue","../../../app/javascript/vue/classes/models/Model.js","../../../app/javascript/vue/classes/models/Comment.js","../../../app/javascript/vue/classes/models/Observation.js","../../../app/javascript/vue/classes/models/Task.js","../../../node_modules/@experiments-labs/rise_ui/src/components/Form/Field.vue","../../../node_modules/@experiments-labs/rise_ui/src/components/Inputs/SubmitButton/SubmitButton.vue","../../../app/javascript/vue/common/DataDisplay/Comments/Form.vue","../../../app/javascript/vue/common/DataDisplay/Comments/_Entry.vue","../../../app/javascript/vue/common/DataDisplay/Comments/List.vue","../../../app/javascript/vue/tools/IsSlotEmpty.js","../../../app/javascript/vue/shapeIcons.js","../../../node_modules/@experiments-labs/rise_ui/src/lib/String.js","../../../app/javascript/vue/classes/models/Placeable.js","../../../app/javascript/vue/classes/models/Element.js","../../../app/javascript/vue/classes/models/Family.js","../../../app/javascript/vue/classes/models/Genus.js","../../../app/javascript/vue/classes/models/Harvest.js","../../../node_modules/@experiments-labs/rise_ui/src/components/Menu/MenuItem.vue","../../../node_modules/@experiments-labs/rise_ui/src/components/Navbar/Navbar.vue","../../../app/javascript/vue/common/ThemeSwitcherMenuItem.vue","../../../app/javascript/vue/classes/models/Map.js","../../../app/javascript/vue/classes/models/User.js","../../../app/javascript/vue/classes/models/Notification.js","../../../app/javascript/vue/classes/models/Patch.js","../../../app/javascript/vue/classes/models/Path.js","../../../node_modules/@experiments-labs/rise_ui/src/components/IconText/IconText.vue","../../../app/javascript/vue/common/DataDisplay/Observation/Observation.vue","../../../app/javascript/vue/apps/garden/components/Observations/_Observations.vue","../../../app/javascript/vue/strokeStylePresets.js","../../../app/javascript/vue/classes/models/Resource.js","../../../node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs","../../../node_modules/@floating-ui/core/dist/floating-ui.core.mjs","../../../node_modules/floating-vue/node_modules/@floating-ui/dom/dist/floating-ui.dom.browser.min.mjs","../../../node_modules/floating-vue/dist/floating-vue.mjs","../../../node_modules/@experiments-labs/rise_ui/src/components/HelpButton/HelpButton.vue","../../../app/javascript/vue/classes/models/ResourceNote.js","../../../app/javascript/vue/classes/models/ResourceInteractionsGroup.js","../../../app/javascript/vue/classes/models/ResourceInteraction.js","../../../node_modules/@experiments-labs/rise_ui/src/components/ListItem/ListItem.vue","../../../app/javascript/vue/classes/models/Account.js","../../../app/javascript/vue/stores/modules/AccountModule.js","../../../app/javascript/vue/stores/modules/Base.js","../../../app/javascript/vue/stores/modules/CommentModule.js","../../../node_modules/mitt/dist/mitt.mjs","../../../app/javascript/vue/tools/EventBus.js","../../../app/javascript/vue/stores/modules/ElementModule.js","../../../app/javascript/vue/stores/modules/FamilyModule.js","../../../app/javascript/vue/stores/modules/GenusModule.js","../../../app/javascript/vue/stores/modules/HarvestModule.js","../../../app/javascript/vue/classes/models/Layer.js","../../../app/javascript/vue/stores/modules/LayerModule.js","../../../app/javascript/vue/stores/modules/LoaderModule.js","../../../app/javascript/vue/stores/modules/MapModule.js","../../../app/javascript/vue/stores/modules/NotificationModule.js","../../../app/javascript/vue/stores/modules/ObservationModule.js","../../../app/javascript/vue/stores/modules/PatchModule.js","../../../app/javascript/vue/stores/modules/PathModule.js","../../../app/javascript/vue/stores/modules/ResourceInteractionModule.js","../../../app/javascript/vue/stores/modules/ResourceInteractionsGroupModule.js","../../../app/javascript/vue/stores/modules/ResourceModule.js","../../../app/javascript/vue/stores/modules/ResourceNoteModule.js","../../../app/javascript/vue/stores/modules/TagModule.js","../../../app/javascript/vue/stores/modules/TaskModule.js","../../../app/javascript/vue/classes/models/TeamMate.js","../../../app/javascript/vue/stores/modules/TeamMateModule.js","../../../app/javascript/vue/stores/modules/UserModule.js","../../../app/javascript/vue/apps/garden/store.js"],"sourcesContent":["\n\n","\n\n","\n\n\n","\n\n\n","import api from '../../tools/api'\n\n/**\n * @typedef {import('vuex').Store} VueXStore\n */\n\nexport default class Model {\n /**\n * Update from another instance\n *\n * @param {Model|object} newInstance - Instance or object to merge data from\n */\n updateAttributes (newInstance) {\n this.constructor.updatableAttributes.forEach((attribute) => {\n if (newInstance[attribute] !== undefined) this[attribute] = newInstance[attribute]\n })\n }\n\n get className () { return this.constructor.getClassName() }\n\n static getClassName () { throw new Error('Class name not defined in model') }\n\n static set updatableAttributes (attributes) { this.UPDATABLE_ATTRIBUTES = attributes }\n\n static get updatableAttributes () { return this.UPDATABLE_ATTRIBUTES }\n\n /* eslint-disable accessor-pairs */\n static set urls (urls) {\n /**\n * @type {object}\n */\n this.urlsList = urls\n }\n /* eslint-enable accessor-pairs */\n\n /**\n * Assigns VueX Store to Store for usage in methods\n *\n * @param {VueXStore} store VueX Store instance\n */\n static set store (store) { this.VueXStore = store }\n\n /**\n * Reach the store\n *\n * @returns {VueXStore} store VueX Store instance\n */\n static get store () { return this.VueXStore }\n\n /**\n * Fetches the list\n *\n * @param {*} params - Parameters for API call\n * @returns {Promise} List of entities\n */\n static getIndex (params) {\n return api('get', this.urlsList.index(params))\n .then(entities => entities.map(entity => new this(entity)))\n }\n\n /**\n * Fetches one entity\n *\n * @param {*} params - Parameters for API call\n * @returns {Promise} Model instance\n */\n static get (params) {\n return api('get', this.urlsList.show(params))\n .then(entity => new this(entity))\n }\n\n /**\n * Creates a new entity\n *\n * @param {*} params - Parameters for API call\n * @returns {Promise} Model instance\n */\n static create (params) {\n return api('post', this.urlsList.create(params), params)\n .then(entity => new this(entity))\n }\n\n /**\n * Updates one entity\n *\n * @param {*} payload - Parameters for API call\n * @returns {Promise} Model instance\n */\n static update (payload) {\n return api('put', this.urlsList.update(payload), payload)\n .then(entity => new this(entity))\n }\n\n /**\n * Destroys one entity\n *\n * @param {*} params - Call parameters\n * @returns {Promise} Nothing on success\n */\n static destroy (params) {\n return api('delete', this.urlsList.destroy(params))\n }\n}\n","import api from '../../tools/api'\nimport Model from './Model'\n\n/**\n * List of attributes that can be updated in `updateAttributes()`\n *\n * @type {string[]}\n */\nconst ATTRIBUTES = ['content', 'removedAt', 'removedByMapOwner', 'userId', 'subjectType', 'subjectId', 'createdAt', 'updatedAt']\n\nclass Comment extends Model {\n /* eslint-disable camelcase, jsdoc/require-param-description */\n /**\n * @param {object} payload - Data from API\n * @param {null|number} payload.id\n * @param {string} payload.content\n * @param {Date|string} payload.removed_at\n * @param {boolean} payload.removed_by_map_owner\n * @param {string} payload.username\n * @param {number} payload.user_id\n * @param {string} payload.subject_type\n * @param {number} payload.subject_id\n * @param {Date|string} payload.created_at\n * @param {Date|string} payload.updated_at\n */\n constructor ({ id = null, content, removed_at, removed_by_map_owner, user_id, username, subject_type, subject_id, created_at, updated_at }) {\n super()\n this.id = id\n this.content = content\n this.removedAt = removed_at ? new Date(removed_at) : null\n this.removedByMapOwner = removed_by_map_owner\n this.userId = user_id\n this.username = username\n this.subjectType = subject_type\n this.subjectId = subject_id\n this.createdAt = created_at ? new Date(created_at) : null\n this.updatedAt = updated_at ? new Date(updated_at) : null\n }\n /* eslint-enable camelcase, jsdoc/require-param-description */\n\n /**\n * Fetches the list\n *\n * @param {*} params - Parameters for API call\n * @returns {Promise} List of entities\n */\n static getIndex ({ subject }) {\n let url\n switch (subject.className) {\n case 'Observation':\n url = this.urlsList.indexForObservation(subject.id)\n break\n case 'Task':\n url = this.urlsList.indexForTask(subject.id)\n break\n default:\n throw new Error(`Unhandled subject type \"${subject.className}\"`)\n }\n return api('get', url)\n .then(entities => entities.map(entity => new this(entity)))\n }\n\n /**\n * @returns {string} The hardcoded class name\n */\n static getClassName () { return 'Comment' }\n\n /**\n * Updates one entity\n *\n * @param {number} id - Comment identifier\n * @returns {Promise} Model instance\n */\n static remove (id) {\n return api('put', this.urlsList.remove(id))\n .then(entity => new this(entity))\n }\n}\n\nComment.updatableAttributes = ATTRIBUTES\nComment.urls = {\n indexForObservation (observationId) { return `/api/observations/${observationId}/comments` },\n indexForTask (taskId) { return `/api/tasks/${taskId}/comments` },\n show (id) { return `/api/comments/${id}` },\n create () { return '/api/comments' },\n update (payload) { return `/api/comments/${payload.id}` },\n remove (id) { return `/api/comments/${id}/remove` },\n}\n\nexport default Comment\n","import api from '../../tools/api'\nimport Model from './Model'\n\nconst OBSERVATION_BASE_URLS = {\n Element: '/api/elements',\n Map: '/api/maps',\n Patch: '/api/patches',\n Path: '/api/paths',\n}\n\n/**\n * List of attributes that can be updated in `updateAttributes()`\n *\n * @type {string[]}\n */\nconst ATTRIBUTES = ['title', 'content', 'subjectType', 'subjectId', 'userId', 'madeAt', 'createdAt', 'updatedAt', 'commentsCount', 'pictures']\n\nclass Observation extends Model {\n /* eslint-disable camelcase, jsdoc/require-param-description */\n /**\n * @param {object} payload - Data from API\n * @param {null|number} payload.id\n * @param {string} payload.title\n * @param {string} payload.content\n * @param {string} payload.subject_type\n * @param {number} payload.subject_id\n * @param {number} payload.user_id\n * @param {Date|string} payload.made_at\n * @param {Date|string} payload.created_at\n * @param {Date|string} payload.updated_at\n * @param {number} payload.comments_count\n * @param {{source: string, thumbnail: string}[]} payload.pictures\n */\n constructor ({ id = null, title, content, subject_type, subject_id, user_id, made_at, created_at, updated_at, comments_count, pictures }) {\n super()\n this.id = id\n this.title = title\n this.content = content\n this.subjectType = subject_type\n this.subjectId = subject_id\n this.userId = user_id\n this.madeAt = made_at ? new Date(made_at) : null\n this.createdAt = created_at ? new Date(created_at) : null\n this.updatedAt = updated_at ? new Date(updated_at) : null\n this.commentsCount = comments_count\n this.pictures = pictures\n }\n /* eslint-enable camelcase, jsdoc/require-param-description */\n\n get subject () {\n switch (this.subjectType) {\n case 'Element':\n return this.constructor.store.getters.element(this.subjectId)\n case 'Map':\n return this.constructor.store.getters.map(this.subjectId)\n case 'Patch':\n return this.constructor.store.getters.patch(this.subjectId)\n case 'Path':\n return this.constructor.store.getters.path(this.subjectId)\n default:\n return null\n }\n }\n\n /**\n * Fetches last observations for given element\n *\n * @param {string} subjectType - Subject type\n * @param {number} subjectId - Subject identifier\n * @returns {Promise} Filtered list of Observation instances\n */\n static getObservationsForSubject (subjectType, subjectId) {\n const baseUrl = OBSERVATION_BASE_URLS[subjectType] || null\n if (!baseUrl) throw new Error(`Unsupported observation type \"${subjectType}\"`)\n\n return api('get', `${baseUrl}/${subjectId}/observations`)\n .then(observations => observations.map(data => new Observation(data)))\n }\n\n /**\n * Fetches all observations for a given map\n *\n * @param {number} mapId - Map identifier\n * @returns {Promise} Filtered list of Observation instances\n */\n static getObservationsForMap (mapId) {\n return api('get', `/api/maps/${mapId}/all_observations`)\n .then(observations => observations.map(data => new Observation(data)))\n }\n\n /**\n * Creates a new observation\n *\n * @param {object} payload - Object with underscored keys\n * @returns {Promise} Observation instance\n */\n static create (payload) {\n const formData = new FormData()\n for (const key of Object.keys(payload)) {\n if (key === 'pictures') {\n for (const file of payload[key]) formData.append(`observation[${key}][]`, file)\n } else { formData.append(`observation[${key}]`, payload[key]) }\n }\n\n return api('post', '/api/observations', formData)\n .then(observation => new Observation(observation))\n }\n\n /**\n * @returns {string} The hardcoded class name\n */\n static getClassName () { return 'Observation' }\n}\n\nObservation.updatableAttributes = ATTRIBUTES\nObservation.urls = {\n index () { return '/api/observations' },\n show (id) { return `/api/observations/${id}` },\n update (payload) { return `/api/observations/${payload.id}` },\n destroy (id) { return `/api/observations/${id}` },\n}\n\nexport default Observation\n","import api from '../../tools/api'\nimport Model from './Model'\n\nconst TASKS_BASE_URLS = {\n Element: '/api/elements',\n Map: '/api/maps',\n Patch: '/api/patches',\n Path: '/api/paths',\n}\n\n/**\n * @typedef {import('./Placeable.js')} Placeable\n */\n\n/**\n * List of attributes that can be updated in `updateAttributes()`\n *\n * @type {string[]}\n */\nconst ATTRIBUTES = ['name', 'notes', 'createdAt', 'updatedAt', 'doneAt', 'plannedFor', 'subjectType', 'subjectId', 'assigneeId', 'updatedSubject', 'commentsCount']\n\nclass Task extends Model {\n /* eslint-disable camelcase, jsdoc/require-param-description */\n /**\n * @param {object} payload - Data from API\n * @param {null|number} payload.id\n * @param {string} payload.name\n * @param {string} payload.notes\n * @param {Date|string} payload.created_at\n * @param {Date|string} payload.updated_at\n * @param {Date|string} payload.done_at\n * @param {Date|string} payload.planned_for\n * @param {string} payload.subject_type\n * @param {number} payload.subject_id\n * @param {number} payload.assignee_id\n * @param {number} payload.comments_count\n * @param {string|null} payload.action\n * @param {object|null} payload.subject\n */\n constructor ({ id = null, name, notes, created_at, updated_at, done_at, planned_for, subject_type, subject_id, assignee_id, comments_count, subject, action }) {\n super()\n this.id = id\n this.name = name\n this.notes = notes\n this.createdAt = created_at ? new Date(created_at) : null\n this.updatedAt = updated_at ? new Date(updated_at) : null\n this.doneAt = done_at ? new Date(done_at) : null\n this.plannedFor = planned_for ? new Date(planned_for) : null\n this.subjectType = subject_type\n this.subjectId = subject_id\n this.assigneeId = assignee_id\n this.commentsCount = comments_count\n this.action = action\n this.updatedSubject = subject\n }\n /* eslint-enable camelcase, jsdoc/require-param-description */\n\n /**\n * Finds the subject in VueX store\n *\n * @returns {Placeable|Map|null} The subject\n */\n get subject () {\n switch (this.subjectType) {\n case 'Element':\n return this.constructor.store.getters.element(this.subjectId)\n case 'Map':\n return this.constructor.store.getters.map(this.subjectId)\n case 'Patch':\n return this.constructor.store.getters.patch(this.subjectId)\n case 'Path':\n return this.constructor.store.getters.path(this.subjectId)\n default:\n return null\n }\n }\n\n /**\n * Fetches last tasks filtered by action for given element\n *\n * @param {number} mapId - Target map identifier\n * @returns {Promise} List of used tasks names\n */\n static getNames (mapId) {\n return api('get', `/api/maps/${mapId}/tasks/names`)\n }\n\n /**\n * Fetches last tasks filtered by action for given element\n *\n * @param {string} subjectType - Subject type\n * @param {number} subjectId - Subject identifier\n * @param {object} filters - Additional filters\n * @param {?string} filters.status - Status filter: `pending`, `done`, `overdue`; default: 'pending'\n * @returns {Promise} Filtered list of Task instances\n */\n static getTasksForSubject (subjectType, subjectId, { status } = {}) {\n const filters = {}\n if (status) filters.status = status\n\n const baseUrl = TASKS_BASE_URLS[subjectType] || null\n if (!baseUrl) throw new Error(`Unsupported subject type \"${subjectType}\"`)\n\n return api('get', `${baseUrl}/${subjectId}/tasks`, { filters })\n .then(tasks => tasks.map(data => new Task(data)))\n }\n\n /**\n * Fetches all tasks for the given map (and its elements)\n *\n * @param {number} mapId - Target map identifier\n * @param {object} filters - Request filters\n * @param {string} filters.status - Filter by status (null for all)\n *\n * @returns {Promise} Filtered list of Task instances\n */\n static getAllForMap (mapId, { status } = {}) {\n const filters = {}\n if (status) filters.status = status\n\n return api('get', `/api/maps/${mapId}/all_tasks`, { filters })\n .then(tasks => tasks.map(data => new Task(data)))\n }\n\n /**\n * @returns {string} The hardcoded class name\n */\n static getClassName () { return 'Task' }\n}\n\nTask.updatableAttributes = ATTRIBUTES\nTask.urls = {\n index (elementId) { return `/api/elements/${elementId}/tasks` },\n show (id) { return `/api/tasks/${id}` },\n create () { return '/api/tasks' },\n update (payload) { return `/api/tasks/${payload.id}` },\n destroy (id) { return `/api/tasks/${id}` },\n}\n\nexport default Task\n","\n\n\n","\n\n\n","