├── .gitignore
├── MANIFEST.in
├── README.md
├── license.txt
├── pibidav
├── __init__.py
├── config
│ ├── __init__.py
│ ├── desktop.py
│ └── docs.py
├── fixtures
│ ├── custom_field.json
│ └── workspace.json
├── hooks.py
├── jinja.py
├── modules.txt
├── patches.txt
├── pibidav
│ ├── __init__.py
│ ├── custom.py
│ ├── doctype
│ │ ├── __init__.py
│ │ ├── attachment_item
│ │ │ ├── __init__.py
│ │ │ ├── attachment_item.json
│ │ │ └── attachment_item.py
│ │ ├── file_category
│ │ │ ├── __init__.py
│ │ │ ├── file_category.js
│ │ │ ├── file_category.json
│ │ │ ├── file_category.py
│ │ │ └── test_file_category.py
│ │ ├── folder_set
│ │ │ ├── __init__.py
│ │ │ ├── folder_set.js
│ │ │ ├── folder_set.json
│ │ │ ├── folder_set.py
│ │ │ ├── folder_set_tree.js
│ │ │ └── test_folder_set.py
│ │ ├── nextcloud_settings
│ │ │ ├── __init__.py
│ │ │ ├── nextcloud_settings.js
│ │ │ ├── nextcloud_settings.json
│ │ │ ├── nextcloud_settings.py
│ │ │ └── test_nextcloud_settings.py
│ │ ├── pibidav_addon
│ │ │ ├── __init__.py
│ │ │ ├── pibidav_addon.js
│ │ │ ├── pibidav_addon.json
│ │ │ ├── pibidav_addon.py
│ │ │ └── test_pibidav_addon.py
│ │ └── reference_item
│ │ │ ├── __init__.py
│ │ │ ├── reference_item.json
│ │ │ └── reference_item.py
│ ├── nextcloud.py
│ └── workspace
│ │ ├── pibidav
│ │ └── pibidav.json
│ │ └── pibitools
│ │ └── pibitools.json
├── public
│ ├── dist
│ │ └── js
│ │ │ ├── nc_browser.bundle.ZRBKKNDW.js
│ │ │ ├── nc_browser.bundle.ZRBKKNDW.js.map
│ │ │ ├── pibidav.bundle.VLVM6LDX.js
│ │ │ └── pibidav.bundle.VLVM6LDX.js.map
│ ├── icons
│ │ └── timeless
│ │ │ └── icons.svg
│ ├── image
│ │ ├── background.png
│ │ ├── favicon.svg
│ │ └── pibiCo_engine_largo.png
│ └── js
│ │ ├── dist
│ │ ├── nc_browser
│ │ │ ├── NcBrowser.vue
│ │ │ ├── TreeNode.vue
│ │ │ └── nc_browser.bundle.js
│ │ ├── nc_pibidav.js
│ │ └── nc_upload.js
│ │ └── pibidav.bundle.js
├── templates
│ ├── __init__.py
│ └── pages
│ │ └── __init__.py
├── translations
│ └── es.csv
└── www
│ └── __init__.py
├── requirements.txt
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pyc
3 | *.egg-info
4 | *.swp
5 | tags
6 | pibidav/docs/current
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include MANIFEST.in
2 | include requirements.txt
3 | include *.json
4 | include *.md
5 | include *.py
6 | include *.txt
7 | recursive-include pibidav *.css
8 | recursive-include pibidav *.csv
9 | recursive-include pibidav *.html
10 | recursive-include pibidav *.ico
11 | recursive-include pibidav *.js
12 | recursive-include pibidav *.json
13 | recursive-include pibidav *.md
14 | recursive-include pibidav *.png
15 | recursive-include pibidav *.py
16 | recursive-include pibidav *.svg
17 | recursive-include pibidav *.txt
18 | recursive-exclude pibidav *.pyc
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## pibiDAV
2 | pibiDAV is a Frappe App to integrate webDAV with a NextCloud Server, used as (DMS), for a copy of Frappe Files uploaded and tagged to NextCloud while uploading files to Frappe.
3 | ## License
4 | MIT# pibiDAV
5 | ## Requirements
6 | Requires a Frappe server instance (refer to https://github.com/frappe/frappe). It also uses a tweaked code of pyocclient but this is embedded already in pibiDAV.
7 | ## Compatibility
8 | PibiDAV branch version-15 is dedicated for Frappe/ERPNext version-15 only.
9 | ## Installation
10 | From the frappe-bench folder, execute
11 | ```
12 | $ bench get-app pibidav --branch version-15 https://github.com/pibico/pibidav.git
13 | $ bench install-app pibidav
14 | ```
15 | If you are using a multi-tenant environment, use the following command
16 | ```
17 | $ bench --site site_name install-app pibidav
18 | ```
19 | ## Features
20 | Once is installed, be aware that you will need to set **developer_mode = 1** on your site_config.json file. Also it is a must to have SSL active in both servers Frappe and NextCloud with specific certificates (wildcard *.domain.com* certificates are not valid for this integration). Letsencrypt Certificates are valid for both servers.
21 | This integration app is prepared for including specific and custom doctypes to upload its attachments to NextCloud at the same time than to Frappe. There is a new frappe.ui.component dialog based on vue.js and called frappe.ui.pibiDocs where to draw the NextCloud Tree and select the destination NextCloud Directory to upload the files.
22 | ### 1. Credentials for NextCloud SuperUser, Backup and DocTypes to Integrate with NextCloud
23 | PibiCo works on NextCloud making the Main Company Folders Superestructure as a shared folder from this NextCloud SuperUser that should be a System Manager on Frappe also. Let's explain with some pictures.
24 | 
25 | This Folder Superstructure has children at different levels and are shared with different groups or users also at different level, thus giving access to these folders and below (both user internal to Company or External such as Customers or Suppliers).
26 | 
27 | At this point, let's go to Frappe Server and once logged-in as System Manager or Administrator we'll go to module pibiDAV on side menu, and on Settings Card we'll choose NextCloud Settings.
28 | 
29 | Once there, we'll activate the NextCloud Enable checkbox (valid also for backup) and fill the credentials of the NextCloud SuperUser in the input fields.
30 | 
31 | We can check that our credentials are correct clicking on NC commands button on upper right side of the screen.
32 | 
33 | Now, automatic uploading of frappe backup is enabled and will be uploaded to the destination folder as given in the backups details section. Frappe Backups files are renamed on NextCloud to files beginning by a number that is the weekday of the backup files, as shown in the picture. So, we will have always the last backup and also all the ancient backups for this weekday as versions in NextCloud, as shown in the picture
34 | 
35 | It's time now of telling to Frappe which doctypes will be integrated to upload its attachments to NextCloud once they are uploaded in Frappe. This is done on the same NextCloud Settings, but on Settings Section, choosing the Frappe Doctype in the table and also giving the DocFields in that DocType that will be used to Tag Automatically the Files on Frappe and On NextCloud as well. We will choose the Sales Invoice Doctype as an example for this configuration. In this case, we will tag the files with the name, the customer and the tax_id from the customer, but whichever field in the doctype, even custom fields are valid.
36 | 
37 | ### 2. Credentials for each Frappe User to Use his NextCloud Account Credentials
38 | To get the permissions from NextCloud into Frappe we will fill the User NextCloud Credentials on Frappe User Settings. We'll go through the user settings and will select the Role NextCloud User first.
39 | 
40 | After that we will go at the bottom of de User Settings Form to provide the NextCloud User Credentials. In this example is the System Manager or Administrator having the SuperUser NextCloud Credentials for having access to the full NextCloud Folder SuperStructure.
41 | 
42 | ### 3. Hooks for NextCloud Integration
43 | Provided we have access to the frappe-bench folder, we must hook the Doctypes included in the integration, by adding the following code to hooks.py of pibidav app:
44 | ```
45 | # doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"}
46 |
47 | nc_list = ["Customer","Project","Sales Invoice","Purchase Invoice","Supplier","Event"]
48 | doctype_js = {}
49 | for item in nc_list:
50 | doctype_js[item] = "public/js/dist/nc_pibidav.js"
51 |
52 | # Home Pages
53 | # ----------
54 | ```
55 | In nc_list variable, we will include whichever doctype to integrate with NextCloud.
56 | #### 2.1 PibiDAV Addon DocType
57 | This new DocType is an extension of existing DocTypes to fill with data given by Attchments, Folders, etc. related to NextCloud and based on its referenced doctype. It is somehow a parallel sheet with data only related to NextCloud Functionalities. It is filled automatically from the different actions derived from NC buttons.
58 | 
59 | ### 4. The magic of the NextCloud Integration inside Frappe
60 | It's time now to try the integration of the NextCloud Folder Structure from Frappe to choose the NC Destination Folder of our uploaded files (except website urls).
61 | Let's go to a doctype of the NC Integration List, i.e. a Sales Invoice. On this core doctype, we'll have two new buttons, for enabling NC and for getting the browser dialog to choose the NC destination folder.
62 | 
63 | First of all, we must enable the NC Integration, clicking on Enable NC button. With this action we will generate the pbc_sales_invoice doctype parallel to our sales invoice (same name with 'pbc_' before it).
64 | 
65 | We can check the created Addon clicking on the Check Addon Button. And return to the sales invoice clicking on the ref_docname on the addon.
66 | 
67 | After having saved the original Sales Invoice as draft we can select the NextCloud Destination Folder for our attachments by clicking on the NC Commands Button and selecting Select NC Folder to bring the pop-up dialog for browsing and selecting our NC Folder.
68 | 
69 | When we select the NextCloud Destination Folder in the dialog, this folder path will be filled in our addon text nc_folder field to remember the destination till it is changed by a new selection.
70 | While we keep this destination folder, all the attachments uploaded to the Sales Invoice will be also uploaded to NextCloud to this folder. Let's create the pdf from the Sales Invoice, signed electronically outside Frappe and uploaded again as attachment in Frappe/ERPNext
71 | 
72 | We have uploaded the attachment to Frappe/ERPNext as shown in the picture
73 | 
74 | Let's Check if it has been also uploaded to NextCloud on the PBC > Customer > Client > Invoices > 2022 as selected.
75 | 
76 | Looking for details we see the pdf file Sales Invoice uploaded in NextCloud Destination, but also it has been created a shared public Link, tagged with customer, tax_id, doctype and name as we defined in the Settings. Voilà, first integration achieved. Let's check the File uploaded to Frappe, it has all metadata from NextCloud as well, and also has some frappe tags also automatically filled on the upload.
77 | 
78 | ### 5. Create folder structures in NextCloud from template Folder Sets in Frappe.
79 | Another possible integration is through a Folder Set Doctype Tree integrated in pibiDav. Folder Set is a Doctype for making Folder Structures taken as templates for recreating them in the NextCloud Instance from a destination folder as root. Let's see in action, once we have the template folder set created in Frappe. We can select the root folder and enable the nc_enable check and select the destination folder in NextCloud where to recreate this structure, renaming the folders in NextCloud upon its creation.
80 | 
81 | We select the destination folder in NextCloud browsing in the dialog.
82 | 
83 | And once selected the destination folder, on the tree we click on button Recreate to perform the copy of folders from Frappe to NextCloud.
84 | 
85 | The result is seen on the image for a new Client Structure called CUSTOMER as abbreviation and Customer Name Details as Description for the Folder.
86 | 
87 | 
88 |
89 | There is an automation to make automatic folders upon creation of selected included doctypes, but try to see if you can make it running. This is an Easter Egg for you to discover.
90 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | License: MIT
--------------------------------------------------------------------------------
/pibidav/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | __version__ = '0.0.1'
3 |
4 |
--------------------------------------------------------------------------------
/pibidav/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/config/__init__.py
--------------------------------------------------------------------------------
/pibidav/config/desktop.py:
--------------------------------------------------------------------------------
1 | from frappe import _
2 |
3 | def get_data():
4 | return [
5 | {
6 | "module_name": "Pibidav",
7 | "color": "grey",
8 | "icon": "octicon octicon-file-directory",
9 | "type": "module",
10 | "label": _("Pibidav")
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/pibidav/config/docs.py:
--------------------------------------------------------------------------------
1 | """
2 | Configuration for docs
3 | """
4 |
5 | # source_link = "https://github.com/[org_name]/pibidav"
6 | # docs_base_url = "https://[org_name].github.io/pibidav"
7 | # headline = "App that does everything"
8 | # sub_heading = "Yes, you got that right the first time, everything"
9 |
10 | def get_context(context):
11 | context.brand_html = "Pibidav"
12 |
--------------------------------------------------------------------------------
/pibidav/fixtures/custom_field.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "allow_in_quick_entry": 0,
4 | "allow_on_submit": 0,
5 | "bold": 0,
6 | "collapsible": 0,
7 | "collapsible_depends_on": null,
8 | "columns": 0,
9 | "default": null,
10 | "depends_on": null,
11 | "description": null,
12 | "docstatus": 0,
13 | "doctype": "Custom Field",
14 | "dt": "Tag",
15 | "fetch_from": null,
16 | "fetch_if_empty": 0,
17 | "fieldname": "uploaded_to_nextcloud",
18 | "fieldtype": "Check",
19 | "hidden": 0,
20 | "hide_border": 0,
21 | "hide_days": 0,
22 | "hide_seconds": 0,
23 | "ignore_user_permissions": 0,
24 | "ignore_xss_filter": 0,
25 | "in_global_search": 0,
26 | "in_list_view": 0,
27 | "in_preview": 0,
28 | "in_standard_filter": 0,
29 | "insert_after": "description",
30 | "is_system_generated": 0,
31 | "is_virtual": 0,
32 | "label": "Uploaded To NextCloud",
33 | "length": 0,
34 | "link_filters": null,
35 | "mandatory_depends_on": null,
36 | "modified": "2022-04-27 09:01:18.884151",
37 | "module": "Pibidav",
38 | "name": "Tag-uploaded_to_nextcloud",
39 | "no_copy": 0,
40 | "non_negative": 0,
41 | "options": null,
42 | "permlevel": 0,
43 | "placeholder": null,
44 | "precision": "",
45 | "print_hide": 0,
46 | "print_hide_if_no_value": 0,
47 | "print_width": null,
48 | "read_only": 1,
49 | "read_only_depends_on": null,
50 | "report_hide": 0,
51 | "reqd": 0,
52 | "search_index": 0,
53 | "show_dashboard": 0,
54 | "sort_options": 0,
55 | "translatable": 0,
56 | "unique": 0,
57 | "width": null
58 | },
59 | {
60 | "allow_in_quick_entry": 0,
61 | "allow_on_submit": 0,
62 | "bold": 0,
63 | "collapsible": 0,
64 | "collapsible_depends_on": null,
65 | "columns": 0,
66 | "default": null,
67 | "depends_on": null,
68 | "description": null,
69 | "docstatus": 0,
70 | "doctype": "Custom Field",
71 | "dt": "Tag",
72 | "fetch_from": null,
73 | "fetch_if_empty": 0,
74 | "fieldname": "tagid",
75 | "fieldtype": "Data",
76 | "hidden": 0,
77 | "hide_border": 0,
78 | "hide_days": 0,
79 | "hide_seconds": 0,
80 | "ignore_user_permissions": 0,
81 | "ignore_xss_filter": 0,
82 | "in_global_search": 0,
83 | "in_list_view": 0,
84 | "in_preview": 0,
85 | "in_standard_filter": 0,
86 | "insert_after": "uploaded_to_nextcloud",
87 | "is_system_generated": 0,
88 | "is_virtual": 0,
89 | "label": "TagId",
90 | "length": 0,
91 | "link_filters": null,
92 | "mandatory_depends_on": null,
93 | "modified": "2022-04-27 09:01:08.998367",
94 | "module": "Pibidav",
95 | "name": "Tag-tagid",
96 | "no_copy": 0,
97 | "non_negative": 0,
98 | "options": null,
99 | "permlevel": 0,
100 | "placeholder": null,
101 | "precision": "",
102 | "print_hide": 0,
103 | "print_hide_if_no_value": 0,
104 | "print_width": null,
105 | "read_only": 1,
106 | "read_only_depends_on": null,
107 | "report_hide": 0,
108 | "reqd": 0,
109 | "search_index": 0,
110 | "show_dashboard": 0,
111 | "sort_options": 0,
112 | "translatable": 0,
113 | "unique": 0,
114 | "width": null
115 | },
116 | {
117 | "allow_in_quick_entry": 0,
118 | "allow_on_submit": 0,
119 | "bold": 0,
120 | "collapsible": 0,
121 | "collapsible_depends_on": null,
122 | "columns": 0,
123 | "default": null,
124 | "depends_on": null,
125 | "description": null,
126 | "docstatus": 0,
127 | "doctype": "Custom Field",
128 | "dt": "Supplier",
129 | "fetch_from": null,
130 | "fetch_if_empty": 0,
131 | "fieldname": "nextcloud",
132 | "fieldtype": "Link",
133 | "hidden": 0,
134 | "hide_border": 0,
135 | "hide_days": 0,
136 | "hide_seconds": 0,
137 | "ignore_user_permissions": 0,
138 | "ignore_xss_filter": 0,
139 | "in_global_search": 0,
140 | "in_list_view": 0,
141 | "in_preview": 0,
142 | "in_standard_filter": 0,
143 | "insert_after": "pb_abbreviation",
144 | "is_system_generated": 0,
145 | "is_virtual": 0,
146 | "label": "Nextcloud",
147 | "length": 0,
148 | "link_filters": null,
149 | "mandatory_depends_on": null,
150 | "modified": "2024-12-06 21:59:37.115047",
151 | "module": "Pibidav",
152 | "name": "Supplier-custom_pd_nextcloud",
153 | "no_copy": 0,
154 | "non_negative": 0,
155 | "options": "PibiDAV Addon",
156 | "permlevel": 0,
157 | "placeholder": null,
158 | "precision": "",
159 | "print_hide": 0,
160 | "print_hide_if_no_value": 0,
161 | "print_width": null,
162 | "read_only": 0,
163 | "read_only_depends_on": null,
164 | "report_hide": 0,
165 | "reqd": 0,
166 | "search_index": 0,
167 | "show_dashboard": 0,
168 | "sort_options": 0,
169 | "translatable": 0,
170 | "unique": 0,
171 | "width": null
172 | },
173 | {
174 | "allow_in_quick_entry": 0,
175 | "allow_on_submit": 1,
176 | "bold": 0,
177 | "collapsible": 0,
178 | "collapsible_depends_on": null,
179 | "columns": 0,
180 | "default": null,
181 | "depends_on": null,
182 | "description": null,
183 | "docstatus": 0,
184 | "doctype": "Custom Field",
185 | "dt": "Customer",
186 | "fetch_from": null,
187 | "fetch_if_empty": 0,
188 | "fieldname": "pb_abbreviation",
189 | "fieldtype": "Data",
190 | "hidden": 0,
191 | "hide_border": 0,
192 | "hide_days": 0,
193 | "hide_seconds": 0,
194 | "ignore_user_permissions": 0,
195 | "ignore_xss_filter": 0,
196 | "in_global_search": 1,
197 | "in_list_view": 1,
198 | "in_preview": 0,
199 | "in_standard_filter": 1,
200 | "insert_after": "customer_group",
201 | "is_system_generated": 0,
202 | "is_virtual": 0,
203 | "label": "Abbreviation",
204 | "length": 0,
205 | "link_filters": null,
206 | "mandatory_depends_on": null,
207 | "modified": "2024-12-06 17:30:57.212078",
208 | "module": "Pibidav",
209 | "name": "Customer-custom_pb_abbreviation",
210 | "no_copy": 0,
211 | "non_negative": 0,
212 | "options": null,
213 | "permlevel": 0,
214 | "placeholder": null,
215 | "precision": "",
216 | "print_hide": 0,
217 | "print_hide_if_no_value": 0,
218 | "print_width": null,
219 | "read_only": 0,
220 | "read_only_depends_on": null,
221 | "report_hide": 0,
222 | "reqd": 1,
223 | "search_index": 0,
224 | "show_dashboard": 0,
225 | "sort_options": 0,
226 | "translatable": 0,
227 | "unique": 1,
228 | "width": null
229 | },
230 | {
231 | "allow_in_quick_entry": 0,
232 | "allow_on_submit": 0,
233 | "bold": 0,
234 | "collapsible": 0,
235 | "collapsible_depends_on": null,
236 | "columns": 0,
237 | "default": null,
238 | "depends_on": null,
239 | "description": null,
240 | "docstatus": 0,
241 | "doctype": "Custom Field",
242 | "dt": "Customer",
243 | "fetch_from": null,
244 | "fetch_if_empty": 0,
245 | "fieldname": "nextcloud",
246 | "fieldtype": "Link",
247 | "hidden": 0,
248 | "hide_border": 0,
249 | "hide_days": 0,
250 | "hide_seconds": 0,
251 | "ignore_user_permissions": 0,
252 | "ignore_xss_filter": 0,
253 | "in_global_search": 0,
254 | "in_list_view": 0,
255 | "in_preview": 0,
256 | "in_standard_filter": 0,
257 | "insert_after": "pb_abbreviation",
258 | "is_system_generated": 0,
259 | "is_virtual": 0,
260 | "label": "Nextcloud",
261 | "length": 0,
262 | "link_filters": null,
263 | "mandatory_depends_on": null,
264 | "modified": "2024-12-08 01:12:24.325454",
265 | "module": "Pibidav",
266 | "name": "Customer-custom_pd_nextcloud",
267 | "no_copy": 0,
268 | "non_negative": 0,
269 | "options": "PibiDAV Addon",
270 | "permlevel": 0,
271 | "placeholder": null,
272 | "precision": "",
273 | "print_hide": 0,
274 | "print_hide_if_no_value": 0,
275 | "print_width": null,
276 | "read_only": 0,
277 | "read_only_depends_on": null,
278 | "report_hide": 0,
279 | "reqd": 0,
280 | "search_index": 0,
281 | "show_dashboard": 0,
282 | "sort_options": 0,
283 | "translatable": 0,
284 | "unique": 0,
285 | "width": null
286 | },
287 | {
288 | "allow_in_quick_entry": 0,
289 | "allow_on_submit": 0,
290 | "bold": 0,
291 | "collapsible": 0,
292 | "collapsible_depends_on": null,
293 | "columns": 0,
294 | "default": null,
295 | "depends_on": null,
296 | "description": null,
297 | "docstatus": 0,
298 | "doctype": "Custom Field",
299 | "dt": "Supplier",
300 | "fetch_from": "nextcloud.nc_folder_internal_link",
301 | "fetch_if_empty": 0,
302 | "fieldname": "nc_folder_link",
303 | "fieldtype": "Read Only",
304 | "hidden": 0,
305 | "hide_border": 0,
306 | "hide_days": 0,
307 | "hide_seconds": 0,
308 | "ignore_user_permissions": 0,
309 | "ignore_xss_filter": 0,
310 | "in_global_search": 0,
311 | "in_list_view": 0,
312 | "in_preview": 0,
313 | "in_standard_filter": 0,
314 | "insert_after": "is_transporter",
315 | "is_system_generated": 0,
316 | "is_virtual": 0,
317 | "label": "NC Folder Link",
318 | "length": 0,
319 | "link_filters": null,
320 | "mandatory_depends_on": null,
321 | "modified": "2024-12-08 12:07:55.697978",
322 | "module": "Pibidav",
323 | "name": "Supplier-custom_pd_nc_folder_link",
324 | "no_copy": 0,
325 | "non_negative": 0,
326 | "options": null,
327 | "permlevel": 0,
328 | "placeholder": null,
329 | "precision": "",
330 | "print_hide": 0,
331 | "print_hide_if_no_value": 0,
332 | "print_width": null,
333 | "read_only": 0,
334 | "read_only_depends_on": null,
335 | "report_hide": 0,
336 | "reqd": 0,
337 | "search_index": 0,
338 | "show_dashboard": 0,
339 | "sort_options": 0,
340 | "translatable": 0,
341 | "unique": 0,
342 | "width": null
343 | },
344 | {
345 | "allow_in_quick_entry": 0,
346 | "allow_on_submit": 0,
347 | "bold": 0,
348 | "collapsible": 0,
349 | "collapsible_depends_on": null,
350 | "columns": 0,
351 | "default": null,
352 | "depends_on": null,
353 | "description": null,
354 | "docstatus": 0,
355 | "doctype": "Custom Field",
356 | "dt": "Customer",
357 | "fetch_from": "nextcloud.nc_folder_internal_link",
358 | "fetch_if_empty": 0,
359 | "fieldname": "nc_folder_link",
360 | "fieldtype": "Read Only",
361 | "hidden": 0,
362 | "hide_border": 0,
363 | "hide_days": 0,
364 | "hide_seconds": 0,
365 | "ignore_user_permissions": 0,
366 | "ignore_xss_filter": 0,
367 | "in_global_search": 0,
368 | "in_list_view": 0,
369 | "in_preview": 0,
370 | "in_standard_filter": 0,
371 | "insert_after": "account_manager",
372 | "is_system_generated": 0,
373 | "is_virtual": 0,
374 | "label": "NC Folder Link",
375 | "length": 0,
376 | "link_filters": null,
377 | "mandatory_depends_on": null,
378 | "modified": "2024-12-08 12:11:23.806930",
379 | "module": "Pibidav",
380 | "name": "Customer-custom_pd_nc_folder_link",
381 | "no_copy": 0,
382 | "non_negative": 0,
383 | "options": null,
384 | "permlevel": 0,
385 | "placeholder": null,
386 | "precision": "",
387 | "print_hide": 0,
388 | "print_hide_if_no_value": 0,
389 | "print_width": null,
390 | "read_only": 0,
391 | "read_only_depends_on": null,
392 | "report_hide": 0,
393 | "reqd": 0,
394 | "search_index": 0,
395 | "show_dashboard": 0,
396 | "sort_options": 0,
397 | "translatable": 0,
398 | "unique": 0,
399 | "width": null
400 | },
401 | {
402 | "allow_in_quick_entry": 0,
403 | "allow_on_submit": 0,
404 | "bold": 0,
405 | "collapsible": 0,
406 | "collapsible_depends_on": null,
407 | "columns": 0,
408 | "default": null,
409 | "depends_on": null,
410 | "description": null,
411 | "docstatus": 0,
412 | "doctype": "Custom Field",
413 | "dt": "File",
414 | "fetch_from": null,
415 | "fetch_if_empty": 0,
416 | "fieldname": "uploaded_to_nextcloud",
417 | "fieldtype": "Check",
418 | "hidden": 0,
419 | "hide_border": 0,
420 | "hide_days": 0,
421 | "hide_seconds": 0,
422 | "ignore_user_permissions": 0,
423 | "ignore_xss_filter": 0,
424 | "in_global_search": 0,
425 | "in_list_view": 0,
426 | "in_preview": 0,
427 | "in_standard_filter": 0,
428 | "insert_after": "uploaded_to_google_drive",
429 | "is_system_generated": 0,
430 | "is_virtual": 0,
431 | "label": "Uploaded To NextCloud",
432 | "length": 0,
433 | "link_filters": null,
434 | "mandatory_depends_on": null,
435 | "modified": "2022-04-14 18:42:39.635285",
436 | "module": "Pibidav",
437 | "name": "File-uploaded_to_nextcloud",
438 | "no_copy": 0,
439 | "non_negative": 0,
440 | "options": null,
441 | "permlevel": 0,
442 | "placeholder": null,
443 | "precision": "",
444 | "print_hide": 0,
445 | "print_hide_if_no_value": 0,
446 | "print_width": null,
447 | "read_only": 1,
448 | "read_only_depends_on": null,
449 | "report_hide": 0,
450 | "reqd": 0,
451 | "search_index": 0,
452 | "show_dashboard": 0,
453 | "sort_options": 0,
454 | "translatable": 0,
455 | "unique": 0,
456 | "width": null
457 | },
458 | {
459 | "allow_in_quick_entry": 0,
460 | "allow_on_submit": 0,
461 | "bold": 0,
462 | "collapsible": 0,
463 | "collapsible_depends_on": null,
464 | "columns": 0,
465 | "default": null,
466 | "depends_on": null,
467 | "description": null,
468 | "docstatus": 0,
469 | "doctype": "Custom Field",
470 | "dt": "File",
471 | "fetch_from": null,
472 | "fetch_if_empty": 0,
473 | "fieldname": "folder_path",
474 | "fieldtype": "Text",
475 | "hidden": 0,
476 | "hide_border": 0,
477 | "hide_days": 0,
478 | "hide_seconds": 0,
479 | "ignore_user_permissions": 0,
480 | "ignore_xss_filter": 0,
481 | "in_global_search": 0,
482 | "in_list_view": 0,
483 | "in_preview": 0,
484 | "in_standard_filter": 0,
485 | "insert_after": "uploaded_to_nextcloud",
486 | "is_system_generated": 0,
487 | "is_virtual": 0,
488 | "label": "Folder Path",
489 | "length": 0,
490 | "link_filters": null,
491 | "mandatory_depends_on": null,
492 | "modified": "2022-04-14 22:39:14.270549",
493 | "module": "Pibidav",
494 | "name": "File-folder_path",
495 | "no_copy": 0,
496 | "non_negative": 0,
497 | "options": null,
498 | "permlevel": 0,
499 | "placeholder": null,
500 | "precision": "",
501 | "print_hide": 0,
502 | "print_hide_if_no_value": 0,
503 | "print_width": null,
504 | "read_only": 1,
505 | "read_only_depends_on": null,
506 | "report_hide": 0,
507 | "reqd": 0,
508 | "search_index": 0,
509 | "show_dashboard": 0,
510 | "sort_options": 0,
511 | "translatable": 0,
512 | "unique": 0,
513 | "width": null
514 | },
515 | {
516 | "allow_in_quick_entry": 0,
517 | "allow_on_submit": 0,
518 | "bold": 0,
519 | "collapsible": 0,
520 | "collapsible_depends_on": null,
521 | "columns": 0,
522 | "default": null,
523 | "depends_on": null,
524 | "description": null,
525 | "docstatus": 0,
526 | "doctype": "Custom Field",
527 | "dt": "File",
528 | "fetch_from": null,
529 | "fetch_if_empty": 0,
530 | "fieldname": "share_link",
531 | "fieldtype": "Data",
532 | "hidden": 0,
533 | "hide_border": 0,
534 | "hide_days": 0,
535 | "hide_seconds": 0,
536 | "ignore_user_permissions": 0,
537 | "ignore_xss_filter": 0,
538 | "in_global_search": 0,
539 | "in_list_view": 0,
540 | "in_preview": 0,
541 | "in_standard_filter": 0,
542 | "insert_after": "folder_path",
543 | "is_system_generated": 0,
544 | "is_virtual": 0,
545 | "label": "Share Link",
546 | "length": 0,
547 | "link_filters": null,
548 | "mandatory_depends_on": null,
549 | "modified": "2022-04-17 09:27:40.367685",
550 | "module": "Pibidav",
551 | "name": "File-share_link",
552 | "no_copy": 0,
553 | "non_negative": 0,
554 | "options": null,
555 | "permlevel": 0,
556 | "placeholder": null,
557 | "precision": "",
558 | "print_hide": 0,
559 | "print_hide_if_no_value": 0,
560 | "print_width": null,
561 | "read_only": 1,
562 | "read_only_depends_on": null,
563 | "report_hide": 0,
564 | "reqd": 0,
565 | "search_index": 0,
566 | "show_dashboard": 0,
567 | "sort_options": 0,
568 | "translatable": 0,
569 | "unique": 0,
570 | "width": null
571 | },
572 | {
573 | "allow_in_quick_entry": 0,
574 | "allow_on_submit": 0,
575 | "bold": 0,
576 | "collapsible": 0,
577 | "collapsible_depends_on": null,
578 | "columns": 0,
579 | "default": null,
580 | "depends_on": null,
581 | "description": null,
582 | "docstatus": 0,
583 | "doctype": "Custom Field",
584 | "dt": "File",
585 | "fetch_from": null,
586 | "fetch_if_empty": 0,
587 | "fieldname": "fileid",
588 | "fieldtype": "Data",
589 | "hidden": 0,
590 | "hide_border": 0,
591 | "hide_days": 0,
592 | "hide_seconds": 0,
593 | "ignore_user_permissions": 0,
594 | "ignore_xss_filter": 0,
595 | "in_global_search": 0,
596 | "in_list_view": 0,
597 | "in_preview": 0,
598 | "in_standard_filter": 0,
599 | "insert_after": "share_link",
600 | "is_system_generated": 0,
601 | "is_virtual": 0,
602 | "label": "FileID",
603 | "length": 0,
604 | "link_filters": null,
605 | "mandatory_depends_on": null,
606 | "modified": "2022-04-26 13:24:09.671191",
607 | "module": "Pibidav",
608 | "name": "File-fileid",
609 | "no_copy": 0,
610 | "non_negative": 0,
611 | "options": null,
612 | "permlevel": 0,
613 | "placeholder": null,
614 | "precision": "",
615 | "print_hide": 0,
616 | "print_hide_if_no_value": 0,
617 | "print_width": null,
618 | "read_only": 1,
619 | "read_only_depends_on": null,
620 | "report_hide": 0,
621 | "reqd": 0,
622 | "search_index": 0,
623 | "show_dashboard": 0,
624 | "sort_options": 0,
625 | "translatable": 0,
626 | "unique": 0,
627 | "width": null
628 | },
629 | {
630 | "allow_in_quick_entry": 0,
631 | "allow_on_submit": 0,
632 | "bold": 0,
633 | "collapsible": 1,
634 | "collapsible_depends_on": null,
635 | "columns": 0,
636 | "default": null,
637 | "depends_on": null,
638 | "description": null,
639 | "docstatus": 0,
640 | "doctype": "Custom Field",
641 | "dt": "User",
642 | "fetch_from": null,
643 | "fetch_if_empty": 0,
644 | "fieldname": "nextcloud_credentials",
645 | "fieldtype": "Section Break",
646 | "hidden": 0,
647 | "hide_border": 0,
648 | "hide_days": 0,
649 | "hide_seconds": 0,
650 | "ignore_user_permissions": 1,
651 | "ignore_xss_filter": 0,
652 | "in_global_search": 0,
653 | "in_list_view": 0,
654 | "in_preview": 0,
655 | "in_standard_filter": 0,
656 | "insert_after": "generate_keys",
657 | "is_system_generated": 0,
658 | "is_virtual": 0,
659 | "label": "NextCloud Credentials",
660 | "length": 0,
661 | "link_filters": null,
662 | "mandatory_depends_on": null,
663 | "modified": "2022-04-01 19:14:50.269324",
664 | "module": "Pibidav",
665 | "name": "User-nextcloud_credentials",
666 | "no_copy": 0,
667 | "non_negative": 0,
668 | "options": null,
669 | "permlevel": 0,
670 | "placeholder": null,
671 | "precision": "",
672 | "print_hide": 0,
673 | "print_hide_if_no_value": 0,
674 | "print_width": null,
675 | "read_only": 0,
676 | "read_only_depends_on": null,
677 | "report_hide": 0,
678 | "reqd": 0,
679 | "search_index": 0,
680 | "show_dashboard": 0,
681 | "sort_options": 0,
682 | "translatable": 0,
683 | "unique": 0,
684 | "width": null
685 | },
686 | {
687 | "allow_in_quick_entry": 1,
688 | "allow_on_submit": 0,
689 | "bold": 0,
690 | "collapsible": 0,
691 | "collapsible_depends_on": null,
692 | "columns": 0,
693 | "default": "0",
694 | "depends_on": null,
695 | "description": null,
696 | "docstatus": 0,
697 | "doctype": "Custom Field",
698 | "dt": "User",
699 | "fetch_from": null,
700 | "fetch_if_empty": 0,
701 | "fieldname": "nextcloud_enable",
702 | "fieldtype": "Check",
703 | "hidden": 0,
704 | "hide_border": 0,
705 | "hide_days": 0,
706 | "hide_seconds": 0,
707 | "ignore_user_permissions": 1,
708 | "ignore_xss_filter": 0,
709 | "in_global_search": 0,
710 | "in_list_view": 0,
711 | "in_preview": 0,
712 | "in_standard_filter": 0,
713 | "insert_after": "nextcloud_credentials",
714 | "is_system_generated": 0,
715 | "is_virtual": 0,
716 | "label": "Enable NextCloud",
717 | "length": 0,
718 | "link_filters": null,
719 | "mandatory_depends_on": null,
720 | "modified": "2022-04-01 19:14:50.269324",
721 | "module": "Pibidav",
722 | "name": "User-nextcloud_enable",
723 | "no_copy": 0,
724 | "non_negative": 0,
725 | "options": null,
726 | "permlevel": 0,
727 | "placeholder": null,
728 | "precision": "",
729 | "print_hide": 0,
730 | "print_hide_if_no_value": 0,
731 | "print_width": null,
732 | "read_only": 0,
733 | "read_only_depends_on": null,
734 | "report_hide": 0,
735 | "reqd": 0,
736 | "search_index": 0,
737 | "show_dashboard": 0,
738 | "sort_options": 0,
739 | "translatable": 0,
740 | "unique": 0,
741 | "width": null
742 | },
743 | {
744 | "allow_in_quick_entry": 1,
745 | "allow_on_submit": 0,
746 | "bold": 0,
747 | "collapsible": 0,
748 | "collapsible_depends_on": null,
749 | "columns": 0,
750 | "default": null,
751 | "depends_on": null,
752 | "description": "NextCloud URL as https://domain.com without / at the end",
753 | "docstatus": 0,
754 | "doctype": "Custom Field",
755 | "dt": "User",
756 | "fetch_from": null,
757 | "fetch_if_empty": 0,
758 | "fieldname": "nextcloud_url",
759 | "fieldtype": "Data",
760 | "hidden": 0,
761 | "hide_border": 0,
762 | "hide_days": 0,
763 | "hide_seconds": 0,
764 | "ignore_user_permissions": 1,
765 | "ignore_xss_filter": 0,
766 | "in_global_search": 0,
767 | "in_list_view": 0,
768 | "in_preview": 0,
769 | "in_standard_filter": 0,
770 | "insert_after": "nextcloud_enable",
771 | "is_system_generated": 0,
772 | "is_virtual": 0,
773 | "label": "NextCloud URL",
774 | "length": 0,
775 | "link_filters": null,
776 | "mandatory_depends_on": null,
777 | "modified": "2022-04-01 19:14:50.979439",
778 | "module": "Pibidav",
779 | "name": "User-nextcloud_url",
780 | "no_copy": 0,
781 | "non_negative": 0,
782 | "options": null,
783 | "permlevel": 0,
784 | "placeholder": null,
785 | "precision": "",
786 | "print_hide": 0,
787 | "print_hide_if_no_value": 0,
788 | "print_width": null,
789 | "read_only": 0,
790 | "read_only_depends_on": null,
791 | "report_hide": 0,
792 | "reqd": 0,
793 | "search_index": 0,
794 | "show_dashboard": 0,
795 | "sort_options": 0,
796 | "translatable": 0,
797 | "unique": 0,
798 | "width": null
799 | },
800 | {
801 | "allow_in_quick_entry": 1,
802 | "allow_on_submit": 0,
803 | "bold": 0,
804 | "collapsible": 0,
805 | "collapsible_depends_on": null,
806 | "columns": 0,
807 | "default": null,
808 | "depends_on": null,
809 | "description": null,
810 | "docstatus": 0,
811 | "doctype": "Custom Field",
812 | "dt": "User",
813 | "fetch_from": null,
814 | "fetch_if_empty": 0,
815 | "fieldname": "nextcloud_username",
816 | "fieldtype": "Data",
817 | "hidden": 0,
818 | "hide_border": 0,
819 | "hide_days": 0,
820 | "hide_seconds": 0,
821 | "ignore_user_permissions": 1,
822 | "ignore_xss_filter": 0,
823 | "in_global_search": 0,
824 | "in_list_view": 0,
825 | "in_preview": 0,
826 | "in_standard_filter": 0,
827 | "insert_after": "nextcloud_url",
828 | "is_system_generated": 0,
829 | "is_virtual": 0,
830 | "label": "Nextcloud Username",
831 | "length": 0,
832 | "link_filters": null,
833 | "mandatory_depends_on": null,
834 | "modified": "2022-04-01 19:14:51.480230",
835 | "module": "Pibidav",
836 | "name": "User-nextcloud_username",
837 | "no_copy": 0,
838 | "non_negative": 0,
839 | "options": null,
840 | "permlevel": 0,
841 | "placeholder": null,
842 | "precision": "",
843 | "print_hide": 0,
844 | "print_hide_if_no_value": 0,
845 | "print_width": null,
846 | "read_only": 0,
847 | "read_only_depends_on": null,
848 | "report_hide": 0,
849 | "reqd": 0,
850 | "search_index": 0,
851 | "show_dashboard": 0,
852 | "sort_options": 0,
853 | "translatable": 0,
854 | "unique": 0,
855 | "width": null
856 | },
857 | {
858 | "allow_in_quick_entry": 1,
859 | "allow_on_submit": 0,
860 | "bold": 0,
861 | "collapsible": 0,
862 | "collapsible_depends_on": null,
863 | "columns": 0,
864 | "default": null,
865 | "depends_on": null,
866 | "description": null,
867 | "docstatus": 0,
868 | "doctype": "Custom Field",
869 | "dt": "User",
870 | "fetch_from": null,
871 | "fetch_if_empty": 0,
872 | "fieldname": "nextcloud_token",
873 | "fieldtype": "Password",
874 | "hidden": 0,
875 | "hide_border": 0,
876 | "hide_days": 0,
877 | "hide_seconds": 0,
878 | "ignore_user_permissions": 1,
879 | "ignore_xss_filter": 0,
880 | "in_global_search": 0,
881 | "in_list_view": 0,
882 | "in_preview": 0,
883 | "in_standard_filter": 0,
884 | "insert_after": "nextcloud_username",
885 | "is_system_generated": 0,
886 | "is_virtual": 0,
887 | "label": "NextCloud Token",
888 | "length": 0,
889 | "link_filters": null,
890 | "mandatory_depends_on": null,
891 | "modified": "2022-04-01 19:14:51.997615",
892 | "module": "Pibidav",
893 | "name": "User-nextcloud_token",
894 | "no_copy": 0,
895 | "non_negative": 0,
896 | "options": null,
897 | "permlevel": 0,
898 | "placeholder": null,
899 | "precision": "",
900 | "print_hide": 0,
901 | "print_hide_if_no_value": 0,
902 | "print_width": null,
903 | "read_only": 0,
904 | "read_only_depends_on": null,
905 | "report_hide": 0,
906 | "reqd": 0,
907 | "search_index": 0,
908 | "show_dashboard": 0,
909 | "sort_options": 0,
910 | "translatable": 0,
911 | "unique": 0,
912 | "width": null
913 | }
914 | ]
--------------------------------------------------------------------------------
/pibidav/fixtures/workspace.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "charts": [],
4 | "content": "[{\"id\":\"w6ozBdED5x\",\"type\":\"header\",\"data\":{\"text\":\"Inicio > pibiTools
\",\"col\":12}},{\"id\":\"Xyxm-ti2im\",\"type\":\"custom_block\",\"data\":{\"custom_block_name\":\"AI Home\",\"col\":12}}]",
5 | "custom_blocks": [],
6 | "docstatus": 0,
7 | "doctype": "Workspace",
8 | "for_user": "",
9 | "hide_custom": 0,
10 | "icon": "pibico",
11 | "indicator_color": "",
12 | "is_hidden": 0,
13 | "label": "pibiTools",
14 | "links": [],
15 | "modified": "2024-12-07 10:10:19.730958",
16 | "module": "Pibidav",
17 | "name": "pibiTools",
18 | "number_cards": [],
19 | "parent_page": "",
20 | "public": 1,
21 | "quick_lists": [],
22 | "restrict_to_domain": null,
23 | "roles": [],
24 | "sequence_id": 3.0,
25 | "shortcuts": [],
26 | "title": "pibiTools"
27 | },
28 | {
29 | "charts": [],
30 | "content": "[{\"id\":\"azQJesz1jX\",\"type\":\"header\",\"data\":{\"text\":\"Inicio > pibiTools > pibiDAV
\",\"col\":12}},{\"id\":\"XQTScKtokJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Documents\",\"col\":4}},{\"id\":\"OIx7Apgo_M\",\"type\":\"card\",\"data\":{\"card_name\":\"Configuración\",\"col\":4}}]",
31 | "custom_blocks": [],
32 | "docstatus": 0,
33 | "doctype": "Workspace",
34 | "for_user": "",
35 | "hide_custom": 0,
36 | "icon": "pibidav",
37 | "indicator_color": "",
38 | "is_hidden": 0,
39 | "label": "pibiDAV",
40 | "links": [
41 | {
42 | "dependencies": null,
43 | "description": null,
44 | "hidden": 0,
45 | "icon": null,
46 | "is_query_report": 0,
47 | "label": "Documents",
48 | "link_count": 4,
49 | "link_to": null,
50 | "link_type": "DocType",
51 | "onboard": 0,
52 | "only_for": null,
53 | "parent": "pibiDAV",
54 | "parentfield": "links",
55 | "parenttype": "Workspace",
56 | "report_ref_doctype": null,
57 | "type": "Card Break"
58 | },
59 | {
60 | "dependencies": null,
61 | "description": null,
62 | "hidden": 0,
63 | "icon": null,
64 | "is_query_report": 0,
65 | "label": "pibiDAV Addon",
66 | "link_count": 0,
67 | "link_to": "PibiDAV Addon",
68 | "link_type": "DocType",
69 | "onboard": 0,
70 | "only_for": null,
71 | "parent": "pibiDAV",
72 | "parentfield": "links",
73 | "parenttype": "Workspace",
74 | "report_ref_doctype": null,
75 | "type": "Link"
76 | },
77 | {
78 | "dependencies": null,
79 | "description": null,
80 | "hidden": 0,
81 | "icon": null,
82 | "is_query_report": 0,
83 | "label": "Tag",
84 | "link_count": 0,
85 | "link_to": "Tag",
86 | "link_type": "DocType",
87 | "onboard": 0,
88 | "only_for": null,
89 | "parent": "pibiDAV",
90 | "parentfield": "links",
91 | "parenttype": "Workspace",
92 | "report_ref_doctype": null,
93 | "type": "Link"
94 | },
95 | {
96 | "dependencies": null,
97 | "description": null,
98 | "hidden": 0,
99 | "icon": null,
100 | "is_query_report": 0,
101 | "label": "Contact",
102 | "link_count": 0,
103 | "link_to": "Contact",
104 | "link_type": "DocType",
105 | "onboard": 0,
106 | "only_for": null,
107 | "parent": "pibiDAV",
108 | "parentfield": "links",
109 | "parenttype": "Workspace",
110 | "report_ref_doctype": null,
111 | "type": "Link"
112 | },
113 | {
114 | "dependencies": null,
115 | "description": null,
116 | "hidden": 0,
117 | "icon": null,
118 | "is_query_report": 0,
119 | "label": "Event",
120 | "link_count": 0,
121 | "link_to": "Event",
122 | "link_type": "DocType",
123 | "onboard": 0,
124 | "only_for": null,
125 | "parent": "pibiDAV",
126 | "parentfield": "links",
127 | "parenttype": "Workspace",
128 | "report_ref_doctype": null,
129 | "type": "Link"
130 | },
131 | {
132 | "dependencies": null,
133 | "description": null,
134 | "hidden": 0,
135 | "icon": null,
136 | "is_query_report": 0,
137 | "label": "Configuración",
138 | "link_count": 3,
139 | "link_to": null,
140 | "link_type": "DocType",
141 | "onboard": 0,
142 | "only_for": null,
143 | "parent": "pibiDAV",
144 | "parentfield": "links",
145 | "parenttype": "Workspace",
146 | "report_ref_doctype": null,
147 | "type": "Card Break"
148 | },
149 | {
150 | "dependencies": null,
151 | "description": null,
152 | "hidden": 0,
153 | "icon": null,
154 | "is_query_report": 0,
155 | "label": "File Category",
156 | "link_count": 0,
157 | "link_to": "File Category",
158 | "link_type": "DocType",
159 | "onboard": 0,
160 | "only_for": null,
161 | "parent": "pibiDAV",
162 | "parentfield": "links",
163 | "parenttype": "Workspace",
164 | "report_ref_doctype": null,
165 | "type": "Link"
166 | },
167 | {
168 | "dependencies": null,
169 | "description": null,
170 | "hidden": 0,
171 | "icon": null,
172 | "is_query_report": 0,
173 | "label": "NextCloud Settings",
174 | "link_count": 0,
175 | "link_to": "NextCloud Settings",
176 | "link_type": "DocType",
177 | "onboard": 0,
178 | "only_for": null,
179 | "parent": "pibiDAV",
180 | "parentfield": "links",
181 | "parenttype": "Workspace",
182 | "report_ref_doctype": null,
183 | "type": "Link"
184 | },
185 | {
186 | "dependencies": null,
187 | "description": null,
188 | "hidden": 0,
189 | "icon": null,
190 | "is_query_report": 0,
191 | "label": "Folder Set",
192 | "link_count": 0,
193 | "link_to": "Folder Set",
194 | "link_type": "DocType",
195 | "onboard": 0,
196 | "only_for": null,
197 | "parent": "pibiDAV",
198 | "parentfield": "links",
199 | "parenttype": "Workspace",
200 | "report_ref_doctype": null,
201 | "type": "Link"
202 | }
203 | ],
204 | "modified": "2024-12-06 20:06:36.470352",
205 | "module": "Pibidav",
206 | "name": "pibiDAV",
207 | "number_cards": [],
208 | "parent_page": "pibiTools",
209 | "public": 1,
210 | "quick_lists": [],
211 | "restrict_to_domain": null,
212 | "roles": [
213 | {
214 | "parent": "pibiDAV",
215 | "parentfield": "roles",
216 | "parenttype": "Workspace",
217 | "role": "Docs Controller"
218 | },
219 | {
220 | "parent": "pibiDAV",
221 | "parentfield": "roles",
222 | "parenttype": "Workspace",
223 | "role": "Docs User"
224 | },
225 | {
226 | "parent": "pibiDAV",
227 | "parentfield": "roles",
228 | "parenttype": "Workspace",
229 | "role": "NextCloud User"
230 | }
231 | ],
232 | "sequence_id": 4.0,
233 | "shortcuts": [],
234 | "title": "pibiDAV"
235 | }
236 | ]
--------------------------------------------------------------------------------
/pibidav/hooks.py:
--------------------------------------------------------------------------------
1 | from . import __version__ as app_version
2 |
3 | app_name = "pibidav"
4 | app_title = "Pibidav"
5 | app_publisher = "pibiCo"
6 | app_description = "WebDAV, CalDAV and CardDAV Integration between Frappe and NextCloud"
7 | app_icon = "octicon octicon-file-directory"
8 | app_color = "grey"
9 | app_email = "pibico.sl@gmail.com"
10 | app_license = "MIT"
11 |
12 | # Includes in
13 | # ------------------
14 |
15 | # include js, css files in header of desk.html
16 | # app_include_css = "/assets/pibidav/css/pibidav.css"
17 | app_include_js = "pibidav.bundle.js"
18 |
19 | # include js, css files in header of web template
20 | # web_include_css = "/assets/pibidav/css/pibidav.css"
21 | # web_include_js = "/assets/pibidav/js/pibidav.js"
22 |
23 | # include custom scss in every website theme (without file extension ".scss")
24 | # website_theme_scss = "pibidav/public/scss/website"
25 |
26 | # include js, css files in header of web form
27 | # webform_include_js = {"doctype": "public/js/doctype.js"}
28 | # webform_include_css = {"doctype": "public/css/doctype.css"}
29 |
30 | # include js in page
31 | # page_js = {"page" : "public/js/file.js"}
32 |
33 | app_include_icons = [
34 | "pibidav/icons/timeless/icons.svg"
35 | ]
36 |
37 | # include js in doctype views
38 | # doctype_js = {"doctype" : "public/js/doctype.js"}
39 | # doctype_list_js = {"doctype" : "public/js/doctype_list.js"}
40 | # doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"}
41 | # doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"}
42 |
43 | nc_list = [
44 | "Contact",
45 | "Event",
46 | "Customer",
47 | "Supplier",
48 | "Project",
49 | "Sales Invoice",
50 | "Sales Order",
51 | "Purchase Invoice",
52 | "Quotation",
53 | "Purchase Order",
54 | "Task",
55 | "Timesheet",
56 | "Item",
57 | "Employee"
58 | ]
59 |
60 | doctype_js = {}
61 | for item in nc_list:
62 | doctype_js[item] = "public/js/dist/nc_pibidav.js"
63 |
64 | # Home Pages
65 | # ----------
66 |
67 | # application home page (will override Website Settings)
68 | # home_page = "login"
69 |
70 | #brand_html = '
pibi
DAV '
71 |
72 | #website_context = {
73 | # "favicon": "/assets/pibidav/image/favicon.svg",
74 | # "splash_image": "/assets/pibidav/image/pibiCo_engine_largo.png"
75 | #}
76 |
77 | # website user home page (by Role)
78 | # role_home_page = {
79 | # "Role": "home_page"
80 | # }
81 |
82 | # Generators
83 | # ----------
84 |
85 | # automatically create page for each record of this doctype
86 | # website_generators = ["Web Page"]
87 |
88 | # Installation
89 | # ------------
90 |
91 | # before_install = "pibidav.install.before_install"
92 | # after_install = "pibidav.install.after_install"
93 |
94 | # Uninstallation
95 | # ------------
96 |
97 | # before_uninstall = "pibidav.uninstall.before_uninstall"
98 | # after_uninstall = "pibidav.uninstall.after_uninstall"
99 |
100 | # Desk Notifications
101 | # ------------------
102 | # See frappe.core.notifications.get_notification_config
103 |
104 | # notification_config = "pibidav.notifications.get_notification_config"
105 |
106 | # Permissions
107 | # -----------
108 | # Permissions evaluated in scripted ways
109 |
110 | # permission_query_conditions = {
111 | # "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions",
112 | # }
113 | #
114 | # has_permission = {
115 | # "Event": "frappe.desk.doctype.event.event.has_permission",
116 | # }
117 |
118 | jinja = {
119 | "methods": [
120 | "pibidav.jinja.timestamp_to_date",
121 | "pibidav.jinja.ts_to_date"
122 | ]
123 | }
124 |
125 | # DocType Class
126 | # ---------------
127 | # Override standard doctype classes
128 |
129 | # override_doctype_class = {
130 | # "ToDo": "custom_app.overrides.CustomToDo"
131 | # }
132 |
133 | # Document Events
134 | # ---------------
135 | # Hook on document methods and events
136 |
137 | doc_events = {
138 | # "*": {
139 | # "after_insert": "pibidav.pibidav.custom.create_nc_folder"
140 | # },
141 | "File": {
142 | "after_insert": ["pibidav.pibidav.custom.upload_file_to_nc"]
143 | }
144 | # "*": {
145 | # "on_update": "method",
146 | # "on_cancel": "method",
147 | # "on_trash": "method"
148 | # }
149 | }
150 |
151 | # Scheduled Tasks
152 | # ---------------
153 |
154 | scheduler_events = {
155 | # "all": [
156 | # "pibidav.tasks.all"
157 | # ],
158 | # "cron": {
159 | # "*/1 * * * *": [
160 | # "pibidav.pibidav.pibical.sync_outside_caldav"
161 | # ]
162 | # },
163 | "daily": [
164 | "pibidav.pibidav.doctype.nextcloud_settings.nextcloud_settings.daily_backup"
165 | ],
166 | # "hourly": [
167 | # "pibidav.tasks.hourly"
168 | # ],
169 | "weekly": [
170 | "pibidav.pibidav.doctype.nextcloud_settings.nextcloud_settings.weekly_backup"
171 | ] #,
172 | # "monthly": [
173 | # "pibidav.tasks.monthly"
174 | # ]
175 | }
176 |
177 | # Testing
178 | # -------
179 |
180 | # before_tests = "pibidav.install.before_tests"
181 |
182 | # Overriding Methods
183 | # ------------------------------
184 | #
185 | # override_whitelisted_methods = {
186 | # "frappe.desk.doctype.event.event.get_events": "pibidav.event.get_events"
187 | # }
188 | #
189 | # each overriding function accepts a `data` argument;
190 | # generated from the base implementation of the doctype dashboard,
191 | # along with any modifications made in other Frappe apps
192 | # override_doctype_dashboards = {
193 | # "Task": "pibidav.task.get_dashboard_data"
194 | # }
195 |
196 | # exempt linked doctypes from being automatically cancelled
197 | #
198 | # auto_cancel_exempted_doctypes = ["Auto Repeat"]
199 |
200 |
201 | # User Data Protection
202 | # --------------------
203 |
204 | user_data_fields = [
205 | {
206 | "doctype": "{doctype_1}",
207 | "filter_by": "{filter_by}",
208 | "redact_fields": ["{field_1}", "{field_2}"],
209 | "partial": 1,
210 | },
211 | {
212 | "doctype": "{doctype_2}",
213 | "filter_by": "{filter_by}",
214 | "partial": 1,
215 | },
216 | {
217 | "doctype": "{doctype_3}",
218 | "strict": False,
219 | },
220 | {
221 | "doctype": "{doctype_4}"
222 | }
223 | ]
224 |
225 | # Authentication and authorization
226 | # --------------------------------
227 |
228 | # auth_hooks = [
229 | # "pibidav.auth.validate"
230 | # ]
231 |
232 | fixtures = [
233 | {
234 | "dt": "Custom Field",
235 | "filters": {"module": ["like", "Pibidav"]}
236 | },
237 | {
238 | "dt": "Workspace",
239 | "filters": {"module": ["like", "Pibidav"]}
240 | }
241 | ]
242 |
243 | treeviews = ['Folder Set']
244 |
245 |
246 | # Translation
247 | # --------------------------------
248 |
249 | # Make link fields search translated document names for these DocTypes
250 | # Recommended only for DocTypes which have limited documents with untranslated names
251 | # For example: Role, Gender, etc.
252 | # translated_search_doctypes = []
253 |
--------------------------------------------------------------------------------
/pibidav/jinja.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 |
3 | import frappe
4 | from datetime import tzinfo, timedelta, datetime
5 |
6 | def timestamp_to_date(value, format='%a %H:%M'):
7 | if value:
8 | return datetime.fromtimestamp(int(value)).strftime(format)
9 |
10 | def ts_to_date(value, format='%a %d/%m/%y %H:%M'):
11 | if value:
12 | return datetime.fromtimestamp(int(value)).strftime(format)
--------------------------------------------------------------------------------
/pibidav/modules.txt:
--------------------------------------------------------------------------------
1 | Pibidav
--------------------------------------------------------------------------------
/pibidav/patches.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/patches.txt
--------------------------------------------------------------------------------
/pibidav/pibidav/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/pibidav/__init__.py
--------------------------------------------------------------------------------
/pibidav/pibidav/custom.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright (c) 2022, PibiCo and contributors
3 | # For license information, please see license.txt
4 | from __future__ import unicode_literals
5 | import frappe
6 | from frappe import _, msgprint, throw, enqueue
7 | from frappe.utils import cint, cstr
8 |
9 | import json, time, requests, sys, hashlib, re, os
10 |
11 | from datetime import date, datetime, timedelta
12 |
13 | import pibidav.pibidav.nextcloud as nextcloud
14 |
15 | from frappe.utils.password import get_decrypted_password
16 | from frappe.utils.file_manager import get_file_path
17 |
18 | import frappe.desk.doctype.tag.tag as tag
19 |
20 | @frappe.whitelist()
21 | def checkNCuser():
22 | ncuser = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_backup_username")
23 | loggeduser = frappe.get_value("User", frappe.session.user, "nextcloud_username")
24 | if ncuser == loggeduser:
25 | return True
26 | else:
27 | return False
28 |
29 | @frappe.whitelist()
30 | def doCreateFolder(doctype):
31 | data = frappe.db.get_value("Reference Item", {"parent": "NextCloud Settings", "reference_doctype": doctype},['create_nc_folder','nc_enable'], as_dict = 1)
32 | if data is None:
33 | return False
34 | if data.create_nc_folder and data.nc_enable:
35 | return True
36 | else:
37 | return False
38 |
39 | @frappe.whitelist()
40 | def create_nc_folder(dt, dn, abbr, strmain, folder_set, sharing_option=None, secret=None):
41 | doc = frappe.get_doc(doctype=dt, docname=dn)
42 | ## Check docs excluded and included in the NC Integration
43 | docs_excluded = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_doctype_excluded")
44 | docs_included = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_doctype_included")
45 | nc_url = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_backup_url")
46 | if nc_url[-1] != '/': nc_url += '/'
47 |
48 | if dt in docs_excluded or not dt in docs_included:
49 | return "DocType not in NC integration {}".format(docs_included)
50 |
51 | data = frappe.db.get_value("Reference Item", {"parent": "NextCloud Settings", "reference_doctype": dt},['nc_folder','create_nc_folder', 'nc_enable'], as_dict = 1)
52 | node_name = folder_set.strip()
53 | path = data.nc_folder
54 |
55 | if path is None:
56 | return "Failed. Not defined the Default destination Folder in NC Settings"
57 |
58 | if not data.nc_enable:
59 | return "Failed. Not enabled NextCloud Integration in Addon"
60 |
61 | if data.create_nc_folder and data.nc_folder != '' and data.folder_set != '':
62 | pibidav = check_addon(dt,dn)
63 |
64 | ## Get default data from NextCloud Settings
65 | ## Assign data to variables for creating folders in NC
66 | strmain = strmain.strip()
67 | abbreviation = abbr.strip()
68 | digits = 3
69 | if path[-1] != '/':
70 | path += '/'
71 | if path[0] != '/':
72 | return frappe.throw(_("{} Root Destination Folder must start with /. Correct in your NextCloud Settings and retry".format(path)))
73 |
74 | root_path = "{}{} {}/".format(path, abbreviation, strmain)
75 |
76 | ## Create Folders if needed data are filled in logged in as superuser in NC
77 | if node_name and path and abbreviation and strmain:
78 | create_nc_dirs(node_name, path, abbreviation, strmain, digits)
79 | nclog = make_nc_session()
80 | ## Get data fileid from dir
81 | fileinfo = nclog.file_info(root_path, properties=['{http://owncloud.org/ns}fileid'])
82 | if fileinfo:
83 | fileid = fileinfo.attributes['{http://owncloud.org/ns}fileid']
84 | ## Create internal Link
85 | intlink = nc_url + 'f/' + fileid
86 | nc_folder_internal_link = '' + intlink + ''
88 | pibidav.nc_folder_internal_link = nc_folder_internal_link
89 |
90 | pibidav.nc_folder = root_path
91 | pibidav.nc_folder_internal_link = nc_folder_internal_link
92 |
93 | ## Create shared Link
94 | if secret is not None or sharing_option is not None:
95 | if sharing_option is None:
96 | pibidav.save()
97 | return
98 | share_option = sharing_option.split('-')
99 | share_option = int(share_option[0])
100 | share_link = nclog.share_file_with_link(path=root_path)
101 | if share_link:
102 | ## Create public link
103 | publink = share_link.get_link()
104 | nc_folder_share_link = '' + publink + ''
106 | pibidav.nc_folder_share_link = nc_folder_share_link
107 | intlink = share_link.get_id()
108 | ## Change perms from read to update
109 | #oth = {'perms': sharing_option, 'secret': secret}
110 | oth = {}
111 | if share_option:
112 | oth = { 'perms': share_option }
113 | pibidav.sharing_option = sharing_option
114 | if secret is not None and secret != '':
115 | oth['password'] = str(secret)
116 | pibidav.secret = secret
117 | nclog.update_share(intlink, **oth)
118 |
119 | pibidav.save()
120 | nclog.logout()
121 |
122 | @frappe.whitelist()
123 | def get_native(parent, filetype):
124 | native_list = frappe.db.get_list('Deliverable Item',
125 | filters={
126 | 'docstatus': ['<', 2],
127 | 'parent': parent,
128 | 'filetype': filetype
129 | },
130 | fields=['attachment','delivery_date'],
131 | order_by='delivery_date desc'
132 | )
133 |
134 | return native_list
135 |
136 | @frappe.whitelist()
137 | def check_nextcloud():
138 | doc = frappe.get_doc("NextCloud Settings", "NextCloud Settings")
139 | nc_url = doc.nc_backup_url
140 | nc_username = doc.nc_backup_username
141 | nc_token = get_decrypted_password('NextCloud Settings', doc.name, 'nc_backup_token', True)
142 | try:
143 | nc = nextcloud.Client(nc_url)
144 | nc.login(nc_username, nc_token)
145 | frappe.msgprint(_("NextCloud Credentials are correct"))
146 | nc.logout()
147 | except:
148 | frappe.throw(_("NextCloud Credentials not correct, please rectify"))
149 |
150 | def make_nc_session_user(user):
151 | if user.nextcloud_enable:
152 | if user.nextcloud_url and user.nextcloud_username and user.nextcloud_token:
153 | nc_token = get_decrypted_password('User', user.name, 'nextcloud_token', False)
154 | try:
155 | _session = nextcloud.Client(user.nextcloud_url)
156 | _session.login(user.nextcloud_username, nc_token)
157 | return _session
158 | except Exception as err:
159 | frappe.throw(_("Error in login in NC: " + str(err)))
160 | return "Failed"
161 | else:
162 | frappe.msgprint(_("User has errors in credentials for NC"))
163 | return "Failed"
164 | else:
165 | frappe.msgprint(_("User has not enabled NC"))
166 | return "Failed"
167 |
168 | @frappe.whitelist()
169 | def get_nc_nodes(path):
170 | nc_user = frappe.get_doc("User", frappe.session.user)
171 | nc = make_nc_session_user(nc_user)
172 |
173 | if nc == "Failed":
174 | return [{"title": "Check NextCloud User Settings"}]
175 |
176 | ## Get DAV List from NC Server
177 | """nc_nodes = nc.list(
178 | path,
179 | depth=1,
180 | properties=[
181 | '{DAV:}getetag',
182 | '{DAV:}getlastmodified',
183 | '{http://owncloud.org/ns}fileid'
184 | ]
185 | )"""
186 | nc_nodes = nc.list(path, depth=1, properties=['{http://owncloud.org/ns}fileid'])
187 |
188 | nodes = []
189 | for row in nc_nodes:
190 | node = {}
191 | if row.file_type == 'dir':
192 | folder = row.path[:-1]
193 | pos = folder.rfind("/")
194 | node['folder'] = 1
195 | node['title'] = folder[pos+1:]
196 | else:
197 | folder = row.path
198 | pos = folder.rfind("/")
199 | node['title'] = folder[pos+1:]
200 | node['path'] = row.path
201 | node['fileid'] = row.attributes['{http://owncloud.org/ns}fileid']
202 | nodes.append(node)
203 |
204 | #nc.logout()
205 |
206 | return nodes
207 |
208 | def tag_file_fp(doc, method=None):
209 | if doc.attached_to_doctype and doc.attached_to_name:
210 | dctype = doc.attached_to_doctype
211 | dcname = doc.attached_to_name
212 | ## Get DocType attached to File
213 | dt = frappe.get_doc(dctype, dcname)
214 | ## Assign default tag to DocType name to the tag list
215 | tag_list = [dctype]
216 | ## Add user tags to tag list if any
217 | if hasattr(dt, "_user_tags"):
218 | if dt._user_tags is not None:
219 | if len(dt._user_tags) > 0:
220 | user_tags = dt._user_tags.split(',')
221 | for lbl in user_tags:
222 | if lbl is not None and lbl not in tag_list and lbl != "": tag_list.append(lbl)
223 | ## Get all docfields for tagging the DocType from NextCloud Settings
224 | _fields_to_tag = frappe.db.get_value("Reference Item", {"parent": "NextCloud Settings", "reference_doctype": dctype}, "reference_docfield")
225 | ## Assign tags to DocType in Frappe (limited length 60 chars due to NextCloud Limits)
226 | if _fields_to_tag:
227 | fields_to_tag = _fields_to_tag.split(',')
228 | for item in fields_to_tag:
229 | try:
230 | if not ',' in dt.get(item):
231 | fp_tag = dt.get(item) #frappe.db.get_value(dctype, dcname, item)
232 | if fp_tag is not None and fp_tag not in tag_list and fp_tag != "": tag_list.append(fp_tag)
233 | for el in tag_list:
234 | if el != '' and el is not None and len(el) > 0 and len(el) <= 60: tag.add_tag(el, "File", doc.name)
235 | except:
236 | pass
237 | else:
238 | tag.add_tag(dctype, "File", doc.name)
239 | else:
240 | tag_list = []
241 |
242 | return tag_list
243 |
244 | def get_tagid(session, tag):
245 | taglist = session.list_tags()
246 | for item in taglist:
247 | if item.attributes['{http://owncloud.org/ns}display-name'] == tag:
248 | tag_id = item.attributes['{http://owncloud.org/ns}id']
249 | return tag_id
250 |
251 | def tag_file_nc(nc_session, filepath, tags):
252 | nc_tags = []
253 | ## Get fileid fron nc uploaded file
254 | remotefile = nc_session.file_info(filepath, properties=['{http://owncloud.org/ns}fileid'])
255 | if remotefile:
256 | fileid = remotefile.attributes['{http://owncloud.org/ns}fileid']
257 | ## Write tags to uploaded file
258 | try:
259 | for tag in tags:
260 | res = nc_session.add_tag(tag)
261 | if res == 409:
262 | tagid = get_tagid(nc_session, tag)
263 | else:
264 | tag_res = res.split('/')
265 | tagid = tag_res[len(tag_res)-1]
266 | if not tagid in nc_tags:
267 | nc_tags.append({"display-name": tag, "tagid": tagid})
268 | ## Add tag to file
269 | nc_session.assign_tag_to_file(fileid, tagid)
270 | except Exception as err:
271 | #return err
272 | nc_tags = []
273 | pass
274 | return fileid, nc_tags
275 |
276 | @frappe.whitelist()
277 | def upload_file_to_nc(doc, method=None):
278 | ## Tag File in Frappe
279 | _tag_list = tag_file_fp(doc)
280 | ## Method only valid for Files, not WebSites
281 | if 'http' in doc.file_url:
282 | return
283 | ## Check docs excluded and included in the NC Integration
284 | docs_excluded = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_doctype_excluded")
285 | docs_included = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_doctype_included")
286 | nc_url = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_backup_url")
287 | if not nc_url:
288 | return
289 | if not nc_url[-1] == '/': nc_url += '/'
290 | ## Check the file attached to parent docType and its inclusion in the list
291 | dt = doc.attached_to_doctype
292 | if docs_excluded and dt:
293 | if dt in docs_excluded:
294 | return
295 | ## Get name of file attached to doctype and file_name and local server path
296 | dn = doc.attached_to_name
297 | file_name = doc.file_name
298 | local_path = get_file_path(file_name)
299 | ## Method only valid for docTypes not being Files
300 | if dt != 'File' and dn:
301 | ## check whether document has NC addon extension active
302 | document = check_addon(dt,dn)
303 |
304 | #document = frappe.get_doc(dt, dn)
305 | ## Check whether doctype has NextCloud Integration active
306 | if not hasattr(document, "nc_enable"):
307 | return
308 | ## Continues if NC Integration is enabled and NC Destination Folder given
309 | if document.nc_enable and document.nc_folder:
310 | local_site = frappe.utils.get_url()
311 | ## Get current logged user and makes session in NC
312 | nc_user = frappe.get_doc("User", frappe.session.user)
313 | nc = make_nc_session_user(nc_user)
314 | if nc == "Failed":
315 | return frappe.msgprint(_("Error in NC Login"))
316 | ## Continues to upload files to NC
317 | nc_path = document.nc_folder + file_name
318 | nc_args = {
319 | 'remote_path': nc_path,
320 | 'local_source_file': local_path
321 | }
322 | ## Upload file to NC
323 | enqueue(method=nc.put_file,queue='short',timeout=300,now=True,**nc_args)
324 | ## Get Shared Link from NC
325 | share = enqueue(method=nc.share_file_with_link, queue='short', timeout=600, now=True, path=nc_path)
326 | ## Update and save File in frappe updated with NC data
327 | doc.uploaded_to_nextcloud = 1
328 | doc.folder_path = document.nc_folder
329 | doc.share_link = share.get_link()
330 |
331 | fileid, nctags = tag_file_nc(nc, nc_path, _tag_list)
332 | doc.fileid = fileid
333 | ## Register nc tagids into frappe tags
334 | if len(nctags) > 0:
335 | for strtag in nctags:
336 | fptag = frappe.get_doc("Tag", strtag['display-name'])
337 | if fptag:
338 | fptag.uploaded_to_nextcloud = 1
339 | fptag.tagid = strtag['tagid']
340 | fptag.save()
341 |
342 | doc.save()
343 | nc.logout()
344 |
345 | return {'fname': doc, 'local_path': local_path, 'local_site': share.get_link()}
346 | else:
347 | return
348 |
349 | @frappe.whitelist()
350 | def get_nc_settings(doctype):
351 | use_default = frappe.get_list("Reference Item", {"parent": "NextCloud Settings", "reference_doctype": doctype}, "use_default_folder")
352 | if use_default:
353 | if use_default[0]['use_default_folder']:
354 | path = frappe.get_list("Reference Item", {"parent": "NextCloud Settings", "reference_doctype": doctype}, "nc_folder")
355 | nc_folder = path[0]['nc_folder']
356 | if nc_folder[-1] != '/': nc_folder + '/'
357 | return nc_folder
358 |
359 | @frappe.whitelist()
360 | def update_attachment_item(dt, dn):
361 | nc_url = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_backup_url")
362 | if not nc_url[-1] == '/': nc_url += '/'
363 | ## Get a list of all files attached to doctype and uploaded to NC
364 | attached_to_doctype = frappe.get_list(
365 | doctype = "File",
366 | fields = ["*"],
367 | filters = [
368 | ["attached_to_doctype", "=", dt],
369 | ["attached_to_name", "=", dn],
370 | ["uploaded_to_nextcloud", "=", 1],
371 | ["docstatus", "<", 1]
372 | ]
373 | )
374 |
375 | doc = frappe.get_doc("PibiDAV Addon", "pbc_" + dn)
376 | if doc is None:
377 | return
378 |
379 | if len(attached_to_doctype) > 0 and hasattr(doc, "nc_enable"):
380 | if hasattr(doc, "attachment_item"):
381 | attachment_item = doc.attachment_item
382 | if len(attachment_item) > 0:
383 | ## Update attachments uploaded to NC
384 | ## Get all files attached to docname
385 | _attachment_item = []
386 | for item in attachment_item:
387 | if item.attachment not in _attachment_item:
388 | _attachment_item.append(item.attachment)
389 | for row in attached_to_doctype:
390 | if row.name not in _attachment_item:
391 | nc_link = 'NextCloud'
394 | json_item = {
395 | "attachment": row.name,
396 | "filename": row.file_name,
397 | "uploaded_to_nc": row.uploaded_to_nextcloud,
398 | "nc_path": row.folder_path,
399 | "nc_link": row.share_link,
400 | "nc_private": nc_url + 'apps/files/?fileid=' + row.fileid,
401 | "nc_url": nc_link
402 | }
403 | doc.append("attachment_item", json_item)
404 | doc.save()
405 | frappe.db.commit()
406 | else:
407 | ## Create new attachment item
408 | for row in attached_to_doctype:
409 | nc_link = 'NextCloud'
412 | json_item = {
413 | "attachment": row.name,
414 | "filename": row.file_name,
415 | "uploaded_to_nc": row.uploaded_to_nextcloud,
416 | "nc_path": row.folder_path,
417 | "nc_link": row.share_link,
418 | "nc_private": nc_url + 'apps/files/?fileid=' + row.fileid,
419 | "nc_url": nc_link
420 | }
421 | doc.append("attachment_item", json_item)
422 | doc.save()
423 | frappe.db.commit()
424 |
425 | @frappe.whitelist()
426 | def upload_nc_file(remote_path, local_file):
427 | ## Get bench path
428 | fname = frappe.get_doc('File', local_file)
429 | ## Only applicable if File is not attached to any doctype
430 | if not fname.attached_to_doctype == 'File' or 'http' in fname.file_url:
431 | return
432 |
433 | local_site = frappe.utils.get_url()
434 | local_path = get_file_path(local_file)
435 | nc_user = frappe.get_doc("User", frappe.session.user)
436 | nc = make_nc_session_user(nc_user)
437 |
438 | if nc == "Failed":
439 | return frappe.msgprint(_("Error in NC Login"))
440 |
441 | nc_args = {
442 | 'remote_path': remote_path,
443 | 'local_source_file': local_path
444 | }
445 | enqueue(method=nc.put_file,queue='short',timeout=300,now=True,**nc_args)
446 |
447 | fname.uploaded_to_nextcloud = 1
448 | fname.folder_path = remote_path.replace(fname.file_name, '')
449 | fname.save()
450 |
451 | nc.logout()
452 |
453 | return {'fname': fname, 'local_path': local_path, 'local_site': local_site}
454 |
455 | @frappe.whitelist()
456 | def get_nc_files_in_folder(folder, start=0, page_length=20):
457 | start = cint(start)
458 | page_length = cint(page_length)
459 | if folder == 0: folder = "/"
460 |
461 | nc_user = frappe.get_doc("User", frappe.session.user)
462 |
463 | nc = make_nc_session_user(nc_user)
464 |
465 | if nc == "Failed":
466 | return {"files": ["Enable NextCloud on User Settings"],
467 | "has_more": 0
468 | }
469 |
470 | ## Get DAV List from NC Server
471 | #nc_nodes = nc.list(path, depth=1, properties=['{DAV:}getetag','{DAV:}getlastmodified','{http://owncloud.org/ns}fileid'])
472 | nc_nodes = nc.list(folder, depth=1, properties=['{http://owncloud.org/ns}fileid', '{DAV:}getlastmodified'])
473 |
474 | nodes = []
475 | for row in nc_nodes:
476 | node = {}
477 | if row.file_type == 'dir':
478 | folder = row.path[:-1]
479 | pos = folder.rfind("/")
480 | node['is_folder'] = 1
481 | node['file_name'] = folder[pos+1:]
482 | else:
483 | folder = row.path
484 | pos = folder.rfind("/")
485 | node['is_folder'] = 0
486 | node['file_name'] = folder[pos+1:]
487 | node['name'] = row.path
488 | node['file_url'] = row.attributes['{http://owncloud.org/ns}fileid']
489 | node['modified'] = row.attributes['{DAV:}getlastmodified']
490 | nodes.append(node)
491 | start += 1
492 | if start == page_length:
493 | break
494 |
495 | #nc.logout()
496 |
497 | return {
498 | 'files': nodes[:page_length],
499 | 'has_more': len(nodes) > page_length
500 | }
501 |
502 | @frappe.whitelist()
503 | def make_nc_session():
504 | nc_settings = frappe.get_doc('NextCloud Settings', 'NextCloud Settings')
505 | if nc_settings.nc_backup_enable:
506 | nc_token = get_decrypted_password('NextCloud Settings', 'NextCloud Settings', 'nc_backup_token', True)
507 | args = {
508 | "verify_certs": False
509 | }
510 | session = nextcloud.Client(nc_settings.nc_backup_url, **args)
511 | session.login(nc_settings.nc_backup_username, nc_token)
512 | return session
513 | else:
514 | frappe.msgprint(_("NextCloud Integration not Enabled"))
515 |
516 | @frappe.whitelist()
517 | def create_nc_group(alias):
518 | ## Login in NC as superuser
519 | nclient = make_nc_session()
520 | ## Create NC Group with name alias
521 | ## Check if group exists first
522 | doGroup = nclient.group_exists(alias.upper())
523 | if doGroup:
524 | frappe.msgprint(_("NC Group Already Exists"))
525 | else:
526 | res = nclient.create_group(alias.upper())
527 | if res:
528 | frappe.msgprint(_("NC Group Created"))
529 | else:
530 | frappe.msgprint(_("Error Creating NC Group"))
531 |
532 | @frappe.whitelist()
533 | def create_nc_dirs(node_name, path, abbrv, strmain, digits):
534 | """ Create folders in NC Instance on path
535 | node_name = '(BPJ) Project'
536 | path = "/Projects/"
537 | abbrv = "PRJ22PBC"
538 | ref_doctype = "pb_Project" ??
539 | strmain = "NC Integration" """
540 |
541 | ## Include tags as Project Name, abbreviation, Customer
542 | ## ----
543 |
544 | ## Login in NC as superuser
545 | nclient = make_nc_session()
546 | ## Create root path and recursively the rest as per origin structure in selected node in folder set
547 | root_node = node_name
548 | n = int(digits)
549 | """
550 | ## Check if selected node is root or not
551 | root_parent = frappe.db.get_value("Folder Set", {"name": node_name}, "root_parent")
552 | if root_parent == root_node:
553 | ## Change title depending on ref_doctype
554 | root_path = path + abbrv + " " + strmain + "/"
555 | else:
556 | root_path = path + node_name[n+1:] + "/"
557 | """
558 | ## Root path is different from the rest of nodes
559 | root_path = "{}{} {}/".format(path, abbrv, strmain)
560 | ## Create first node in NC
561 | folder = nclient.mkdir(root_path)
562 | ## If dir is created in NC, continues recursively with its children
563 | if folder:
564 | children = get_children(nclient, root_node, root_path, abbrv, n)
565 | else:
566 | frappe.msgprint(_("Error creating root folder in NC"))
567 |
568 | return frappe.msgprint(_("Successfully Created Folders in NC"))
569 |
570 | def get_children(session, parent_node, parent_path, abr, n):
571 | children_list = []
572 | ## Get all children folders only for given node
573 | children = frappe.get_list(
574 | doctype = "Folder Set",
575 | filters = {
576 | "is_group": 1,
577 | "parent_folder_set": parent_node
578 | },
579 | fields = ["name", "parent_folder_set", "is_group"],
580 | order_by = "creation asc"
581 | )
582 | ## Get recursively the rest of children an create folders in NC
583 | if len(children) > 0:
584 | for child in children:
585 | if child.name not in children_list: children_list.append(child.name)
586 | parent_path_child = "{}{} {}/".format(parent_path, abr, child.name[n+1:])
587 | ## Create folder in NC
588 | folder = session.mkdir(parent_path_child)
589 | ## If folder is created continues recursively
590 | if folder:
591 | get_children(session, child.name, parent_path_child, abr, n)
592 | else:
593 | frappe.msgprint(_("Error creating child folder in NC"))
594 |
595 | return children_list
596 |
597 | def check_addon(dt, dn):
598 | ## First we'll check and create pibiDAV Addon doctype related
599 | addon_list = frappe.db.get_list('PibiDAV Addon',
600 | filters={
601 | 'docstatus': ['<', 2],
602 | 'name': "pbc_{}".format(dn)
603 | },
604 | fields=['*']
605 | )
606 | if len(addon_list) == 0:
607 | ## Create pibiDAV Addon doctype
608 | pibidav = frappe.new_doc("PibiDAV Addon")
609 | pibidav.ref_doctype = dt
610 | pibidav.ref_docname = dn
611 | ## Get default data from NextCloud Settings
612 | settings = frappe.db.get_value("Reference Item", {"parent": "NextCloud Settings", "reference_doctype": dt},['nc_folder'], as_dict = 1)
613 | if settings is not None:
614 | if settings.use_default_folder and settings.nc_folder:
615 | pibidav.nc_folder = settings.nc_folder
616 | pibidav.insert()
617 | frappe.db.commit()
618 | else:
619 | pibidav = frappe.get_doc("PibiDAV Addon", "pbc_{}".format(dn))
620 |
621 | return pibidav
622 |
623 | @frappe.whitelist()
624 | def fetch_nc_folder_internal_link_from_addon(addon_name):
625 | pibidav = frappe.get_doc("PibiDAV Addon", addon_name)
626 | if not pibidav.nc_folder:
627 | frappe.throw(_("No NC Folder defined in the Addon."))
628 |
629 | session = make_nc_session() # Authenticate as superuser
630 | fileinfo = session.file_info(pibidav.nc_folder, properties=['{http://owncloud.org/ns}fileid'])
631 | if fileinfo:
632 | fileid = fileinfo.attributes['{http://owncloud.org/ns}fileid']
633 | nc_url = frappe.get_value("NextCloud Settings", "NextCloud Settings", "nc_backup_url")
634 | if nc_url[-1] != '/':
635 | nc_url += '/'
636 | intlink = f'{nc_url}f/{fileid}'
637 | pibidav.nc_folder_internal_link = intlink
638 | pibidav.save()
639 | return intlink
640 | else:
641 | frappe.throw(_("Failed to fetch folder metadata from NextCloud."))
642 |
643 | @frappe.whitelist()
644 | def get_folder_path_from_link(fileid):
645 | """
646 | Retrieves the full folder path using the fileid.
647 |
648 | :param fileid: File ID from the NextCloud folder link
649 | :return: Full path of the folder or an error message
650 | """
651 | if not fileid:
652 | frappe.log_error("No fileid provided to get_folder_path_from_link.")
653 | return "Error: fileid is empty."
654 |
655 | try:
656 | # Create a NextCloud session
657 | nc_session = make_nc_session()
658 | if not nc_session or nc_session == "Failed":
659 | frappe.log_error("Failed to establish session with NextCloud.")
660 | return "Error: Unable to establish session with NextCloud."
661 |
662 | # Log the fileid for debugging
663 | frappe.logger().info(f"Fetching directory for fileid: {fileid}")
664 |
665 | # Use the NextCloud session to fetch the folder path
666 | folder_path = nc_session.get_path_from_fileid(fileid)
667 | #nc_session.logout()
668 |
669 | if folder_path:
670 | frappe.logger().info(f"Retrieved folder path for fileid {fileid}: {folder_path}")
671 | return folder_path
672 | else:
673 | frappe.log_error(f"Folder path not found for fileid: {fileid}")
674 | return "Folder path not found."
675 | except Exception as e:
676 | # Log the error with a full traceback for debugging
677 | frappe.log_error(message=f"Error retrieving folder path for fileid {fileid}: {e}", title="NextCloud Path Retrieval Error")
678 | return f"Error retrieving folder path: {e}"
679 |
680 | @frappe.whitelist()
681 | def create_nc_subfolder(parent_folder, folder_name):
682 | try:
683 | session = make_nc_session()
684 | if session == "Failed":
685 | return frappe.throw(_("Error in NC Login"))
686 |
687 | # Ensure parent folder starts with /
688 | if not parent_folder.startswith('/'):
689 | parent_folder = '/' + parent_folder
690 |
691 | # Create full path
692 | new_folder_path = f"{parent_folder}/{folder_name}"
693 | if new_folder_path.startswith('//'):
694 | new_folder_path = new_folder_path[1:]
695 |
696 | # Create folder using NextCloud client
697 | session.mkdir(new_folder_path)
698 | session.logout()
699 |
700 | return new_folder_path
701 |
702 | except Exception as e:
703 | frappe.log_error(message=f"Error creating NextCloud subfolder: {str(e)}", title="NextCloud Folder Creation Error")
704 | return frappe.throw(_("Failed to create folder in NextCloud: {0}").format(str(e)))
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/pibidav/doctype/__init__.py
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/attachment_item/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/pibidav/doctype/attachment_item/__init__.py
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/attachment_item/attachment_item.json:
--------------------------------------------------------------------------------
1 | {
2 | "actions": [],
3 | "allow_rename": 1,
4 | "creation": "2022-04-17 09:45:52.593268",
5 | "doctype": "DocType",
6 | "editable_grid": 1,
7 | "engine": "InnoDB",
8 | "field_order": [
9 | "attachment",
10 | "file_category",
11 | "filename",
12 | "cb_01",
13 | "uploaded_to_nc",
14 | "nc_path",
15 | "nc_link",
16 | "nc_private",
17 | "nc_url"
18 | ],
19 | "fields": [
20 | {
21 | "fieldname": "attachment",
22 | "fieldtype": "Link",
23 | "in_list_view": 1,
24 | "label": "Attachment",
25 | "options": "File",
26 | "reqd": 1
27 | },
28 | {
29 | "fieldname": "file_category",
30 | "fieldtype": "Link",
31 | "in_list_view": 1,
32 | "label": "File Type",
33 | "options": "File Category"
34 | },
35 | {
36 | "fetch_from": "attachment.file_name",
37 | "fieldname": "filename",
38 | "fieldtype": "Data",
39 | "in_list_view": 1,
40 | "label": "Filename",
41 | "read_only": 1
42 | },
43 | {
44 | "default": "0",
45 | "fetch_from": "attachment.uploaded_to_nextcloud",
46 | "fieldname": "uploaded_to_nc",
47 | "fieldtype": "Check",
48 | "in_list_view": 1,
49 | "label": "Uploaded To NC",
50 | "read_only": 1
51 | },
52 | {
53 | "fetch_from": "attachment.folder_path",
54 | "fieldname": "nc_path",
55 | "fieldtype": "Text",
56 | "in_list_view": 1,
57 | "label": "NC Path",
58 | "read_only": 1
59 | },
60 | {
61 | "fetch_from": "attachment.share_link",
62 | "fieldname": "nc_link",
63 | "fieldtype": "Data",
64 | "in_list_view": 1,
65 | "label": "NC Share Link",
66 | "read_only": 1
67 | },
68 | {
69 | "fieldname": "nc_private",
70 | "fieldtype": "Data",
71 | "in_list_view": 1,
72 | "label": "NC Private Link",
73 | "read_only": 1
74 | },
75 | {
76 | "fieldname": "nc_url",
77 | "fieldtype": "Read Only",
78 | "label": "NC URL"
79 | },
80 | {
81 | "fieldname": "cb_01",
82 | "fieldtype": "Column Break",
83 | "label": "NexCloud"
84 | }
85 | ],
86 | "index_web_pages_for_search": 1,
87 | "istable": 1,
88 | "links": [],
89 | "modified": "2022-05-03 17:53:23.263098",
90 | "modified_by": "Administrator",
91 | "module": "Pibidav",
92 | "name": "Attachment Item",
93 | "owner": "Administrator",
94 | "permissions": [],
95 | "sort_field": "modified",
96 | "sort_order": "DESC"
97 | }
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/attachment_item/attachment_item.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022, pibiCo and contributors
2 | # For license information, please see license.txt
3 |
4 | # import frappe
5 | from frappe.model.document import Document
6 |
7 | class AttachmentItem(Document):
8 | pass
9 |
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/file_category/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/pibidav/doctype/file_category/__init__.py
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/file_category/file_category.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022, pibiCo and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on('File Category', {
5 | // refresh: function(frm) {
6 |
7 | // }
8 | });
9 |
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/file_category/file_category.json:
--------------------------------------------------------------------------------
1 | {
2 | "actions": [],
3 | "allow_rename": 1,
4 | "autoname": "field:title",
5 | "creation": "2022-04-27 10:19:29.164957",
6 | "doctype": "DocType",
7 | "document_type": "Setup",
8 | "editable_grid": 1,
9 | "engine": "InnoDB",
10 | "field_order": [
11 | "title",
12 | "description"
13 | ],
14 | "fields": [
15 | {
16 | "fieldname": "title",
17 | "fieldtype": "Data",
18 | "label": "title",
19 | "unique": 1
20 | },
21 | {
22 | "fieldname": "description",
23 | "fieldtype": "Text",
24 | "label": "Description"
25 | }
26 | ],
27 | "index_web_pages_for_search": 1,
28 | "links": [],
29 | "modified": "2022-04-28 14:10:20.613874",
30 | "modified_by": "Administrator",
31 | "module": "Pibidav",
32 | "name": "File Category",
33 | "owner": "Administrator",
34 | "permissions": [
35 | {
36 | "create": 1,
37 | "delete": 1,
38 | "email": 1,
39 | "export": 1,
40 | "print": 1,
41 | "read": 1,
42 | "report": 1,
43 | "role": "System Manager",
44 | "share": 1,
45 | "write": 1
46 | },
47 | {
48 | "create": 1,
49 | "delete": 1,
50 | "email": 1,
51 | "export": 1,
52 | "print": 1,
53 | "read": 1,
54 | "report": 1,
55 | "role": "Docs Controller",
56 | "share": 1,
57 | "write": 1
58 | },
59 | {
60 | "email": 1,
61 | "export": 1,
62 | "print": 1,
63 | "read": 1,
64 | "report": 1,
65 | "role": "Docs User",
66 | "share": 1
67 | },
68 | {
69 | "email": 1,
70 | "export": 1,
71 | "print": 1,
72 | "read": 1,
73 | "report": 1,
74 | "role": "NextCloud User",
75 | "share": 1
76 | },
77 | {
78 | "read": 1,
79 | "role": "Vendor"
80 | }
81 | ],
82 | "sort_field": "modified",
83 | "sort_order": "DESC",
84 | "track_changes": 1
85 | }
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/file_category/file_category.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022, pibiCo and contributors
2 | # For license information, please see license.txt
3 |
4 | # import frappe
5 | from frappe.model.document import Document
6 |
7 | class FileCategory(Document):
8 | pass
9 |
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/file_category/test_file_category.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022, pibiCo and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | import unittest
6 |
7 | class TestFileCategory(unittest.TestCase):
8 | pass
9 |
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/folder_set/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/pibidav/doctype/folder_set/__init__.py
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/folder_set/folder_set.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022, pibiCo and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on('Folder Set', {
5 | select_nc_folder: function(frm) {
6 | new frappe.ui.pibiDocs;
7 | }
8 | });
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/folder_set/folder_set.json:
--------------------------------------------------------------------------------
1 | {
2 | "actions": [],
3 | "allow_rename": 1,
4 | "creation": "2022-04-21 19:00:30.884664",
5 | "doctype": "DocType",
6 | "document_type": "Setup",
7 | "editable_grid": 1,
8 | "engine": "InnoDB",
9 | "field_order": [
10 | "is_group",
11 | "title",
12 | "cb_01",
13 | "select_nc_folder",
14 | "old_parent",
15 | "root_parent",
16 | "parent_folder_set",
17 | "nc_folder",
18 | "lft",
19 | "rgt"
20 | ],
21 | "fields": [
22 | {
23 | "default": "0",
24 | "fieldname": "is_group",
25 | "fieldtype": "Check",
26 | "label": "Is Folder"
27 | },
28 | {
29 | "fieldname": "title",
30 | "fieldtype": "Data",
31 | "in_list_view": 1,
32 | "label": "Title",
33 | "reqd": 1,
34 | "unique": 1
35 | },
36 | {
37 | "fieldname": "cb_01",
38 | "fieldtype": "Column Break"
39 | },
40 | {
41 | "fieldname": "old_parent",
42 | "fieldtype": "Link",
43 | "label": "Old Parent",
44 | "options": "Folder Set"
45 | },
46 | {
47 | "fieldname": "root_parent",
48 | "fieldtype": "Link",
49 | "label": "Root Parent",
50 | "options": "Folder Set"
51 | },
52 | {
53 | "fieldname": "parent_folder_set",
54 | "fieldtype": "Link",
55 | "label": "Parent Folder Set",
56 | "options": "Folder Set"
57 | },
58 | {
59 | "fieldname": "nc_folder",
60 | "fieldtype": "Text",
61 | "label": "NC Folder"
62 | },
63 | {
64 | "fieldname": "lft",
65 | "fieldtype": "Int",
66 | "hidden": 1,
67 | "label": "Left",
68 | "no_copy": 1,
69 | "read_only": 1
70 | },
71 | {
72 | "fieldname": "rgt",
73 | "fieldtype": "Int",
74 | "hidden": 1,
75 | "label": "Right",
76 | "no_copy": 1,
77 | "read_only": 1
78 | },
79 | {
80 | "fieldname": "select_nc_folder",
81 | "fieldtype": "Button",
82 | "label": "Select NC Folder"
83 | }
84 | ],
85 | "icon": "folder",
86 | "index_web_pages_for_search": 1,
87 | "is_tree": 1,
88 | "links": [],
89 | "modified": "2022-05-11 10:34:30.594028",
90 | "modified_by": "Administrator",
91 | "module": "Pibidav",
92 | "name": "Folder Set",
93 | "nsm_parent_field": "parent_folder_set",
94 | "owner": "Administrator",
95 | "permissions": [
96 | {
97 | "create": 1,
98 | "delete": 1,
99 | "email": 1,
100 | "export": 1,
101 | "print": 1,
102 | "read": 1,
103 | "report": 1,
104 | "role": "System Manager",
105 | "share": 1,
106 | "write": 1
107 | },
108 | {
109 | "create": 1,
110 | "delete": 1,
111 | "email": 1,
112 | "export": 1,
113 | "print": 1,
114 | "read": 1,
115 | "report": 1,
116 | "role": "All",
117 | "share": 1,
118 | "write": 1
119 | }
120 | ],
121 | "quick_entry": 1,
122 | "search_fields": "root_parent,parent_folder_set",
123 | "sort_field": "modified",
124 | "sort_order": "DESC",
125 | "title_field": "title"
126 | }
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/folder_set/folder_set.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022, pibiCo and contributors
2 | # For license information, please see license.txt
3 |
4 | import frappe
5 | from frappe import _
6 | from frappe.utils.nestedset import NestedSet
7 |
8 | import frappe.model.rename_doc
9 |
10 | class FolderSet(NestedSet):
11 | def before_save(doc):
12 | if doc.parent_folder_set and doc.parent_folder_set != '':
13 | doc.root_parent = frappe.db.get_value('Folder Set', doc.parent_folder_set, 'root_parent')
14 |
15 | def after_insert(doc):
16 | old_name = doc.name
17 | r = frappe.db.get_value('Folder Set', doc.title, 'name')
18 | if r and r == doc.title:
19 | doc.name = doc.title + ' (' + old_name + ')'
20 | else:
21 | doc.name = doc.title
22 |
23 | if not doc.parent_folder_set or doc.parent_folder_set == '':
24 | doc.root_parent = doc.name
25 | frappe.db.set_value('Folder Set', old_name, {
26 | 'name': doc.name,
27 | 'root_parent': doc.root_parent,
28 | 'title': doc.name
29 | }, update_modified=False)
30 |
31 | @frappe.whitelist()
32 | def get_children(doctype, parent='', **filters):
33 | return _get_children(doctype, parent)
34 |
35 | def _get_children(doctype, parent='', ignore_permissions=False):
36 | parent_field = 'parent_' + doctype.lower().replace(' ', '_')
37 | filters = [['ifnull(`{0}`,"")'.format(parent_field), '=', parent],
38 | ['docstatus', '<' ,'2']]
39 |
40 | meta = frappe.get_meta(doctype)
41 |
42 | return frappe.get_list(
43 | doctype,
44 | fields=[
45 | 'name as value',
46 | '{0} as title'.format(meta.get('title_field') or 'name'),
47 | 'is_group as expandable'
48 | ],
49 | filters=filters,
50 | order_by='title',
51 | ignore_permissions=ignore_permissions
52 | )
53 |
54 | @frappe.whitelist()
55 | def rename(old, new, debug=False):
56 | return frappe.model.rename_doc.rename_doc('Folder Set', old, new, debug)
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/folder_set/folder_set_tree.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022, pibiCo and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.provide("frappe.treeview_settings");
5 | frappe.provide('frappe.views');
6 |
7 | frappe.treeview_settings['Folder Set'] = {
8 | breadcrumbs: "Templates",
9 | title: __('Folder Set'),
10 | get_tree_root: false,
11 | root_label: "",
12 | get_tree_nodes: 'pibidav.pibidav.doctype.folder_set.folder_set.get_children',
13 | filters: [
14 | {
15 | fieldname: "root_parent",
16 | fieldtype: "Link",
17 | options: "Folder Set",
18 | label: __("Tree"),
19 | default: "BPJ Big Project",
20 | get_query: function() {
21 | var args = [
22 | ["Folder Set", 'is_group', '=', 1],
23 | ["Folder Set", 'parent_folder_set', '=', '']
24 | ];
25 | return {filters: args};
26 | }
27 | }
28 | ],
29 | post_render: function(treeview) {
30 | treeview.args['is_group'] = 1;
31 | },
32 | extend_toolbar: false,
33 | toolbar: [
34 | {
35 | label:__("Edit"),
36 | condition: function(node) {
37 | var me = frappe.views.trees['Folder Set'];
38 | return !node.is_root && me.can_read;
39 | },
40 | click: function(node) {
41 | var me = frappe.views.trees['Folder Set'];
42 | frappe.set_route("Form", me.doctype, node.label);
43 | }
44 | },
45 | {
46 | label:__("Add Child"),
47 | condition: function(node) {
48 | var me = frappe.views.trees['Folder Set'];
49 | if (me.can_create && node.expandable && !node.hide_add) {
50 | try {
51 | if (node.parent_node.hide_add) { node.hide_add = true; }
52 | }
53 | catch (e) { }
54 | }
55 | return me.can_create && node.expandable && !node.hide_add;
56 | },
57 | click: function(node) {
58 | var me = frappe.views.trees['Folder Set'];
59 | me.new_node();
60 | }//,
61 | //btnClass: "hidden-xs"
62 | },
63 | {
64 | label:__("Delete"),
65 | async: false,
66 | condition: function(node) {
67 | var allow_delete = true;
68 | var me = frappe.views.trees['Folder Set'];
69 | try { if (node.parent_node.hide_add) { allow_delete = false; }
70 | } catch (e) { }
71 | if (allow_delete && me.can_delete && !node.is_root && !node.hide_add && node.expandable) {
72 | frappe.call({
73 | method: 'frappe.client.get_value',
74 | args: {
75 | 'doctype': 'Folder Set',
76 | 'filters': {'parent_folder_set' : node.label},
77 | 'fieldname': [ 'name' ]
78 | },
79 | async: false,
80 | callback: function(r) {
81 | if (!r.exc) {
82 | if (r.message.name && r.message.name !="" && r.message.name != null) allow_delete = false;
83 | return allow_delete;
84 | }
85 | }
86 | });
87 | }
88 | return allow_delete && me.can_delete && !node.is_root && !node.hide_add;
89 | },
90 | click: function(node) {
91 | var me = frappe.views.trees['Folder Set'];
92 | frappe.model.delete_doc(me.doctype, node.label, function() {
93 | node.parent.remove();
94 | });
95 | }//,
96 | //btnClass: "hidden-xs"
97 | },
98 | {
99 | label:__("Recreate"),
100 | condition: function(node) {
101 | var allow_create = true;
102 | var me = frappe.views.trees['Folder Set'];
103 | if (node.is_root) { allow_create = false; }
104 | return allow_create && !node.is_root && !node.hide_add;
105 | },
106 | click: function(node) {
107 | var upload2nc = true;
108 | frappe.db.get_value('Folder Set', {'name': node.title}, 'nc_folder', (r) => {
109 | let nc_folder = r.nc_folder;
110 | if (nc_folder) {
111 | frappe.call({
112 | method: "pibidav.pibidav.custom.checkNCuser",
113 | args: {
114 | }
115 | }).then(function(r) {
116 | let isUser = r.message;
117 | if (isUser) {
118 | let d = new frappe.ui.Dialog({
119 | title: __("Recreate Folders in NC"),
120 | fields: [
121 | { label: __("Parent Path"), fieldname: "parent_path", fieldtype: "Data", default: nc_folder},
122 | { label: __("Abbreviation"), fieldname: "abbreviation", fieldtype: "Data", default: "PRJYYABV"},
123 | { label: __("Root Dir Name"), fieldname: "folder_name", fieldtype: "Data"},
124 | { label: __("Digits to substitute with abbreviation"), fieldname: "digits", fieldtype: "Int", default: 3}
125 | ],
126 | primary_action_label: __("Create"),
127 | primary_action(values) {
128 | //console.log(values);
129 | frappe.call({
130 | method: "pibidav.pibidav.custom.create_nc_dirs",
131 | args: {
132 | node_name: node.title,
133 | path: values.parent_path,
134 | abbrv: values.abbreviation,
135 | strmain: values.folder_name,
136 | digits: values.digits
137 | },
138 | callback: function(r) {
139 | console.log(r.message);
140 | }
141 | });
142 | d.hide();
143 | }
144 | });
145 | d.show();
146 | } else {
147 | frappe.msgprint(__("Only NextCloud SuperUser can use this method"));
148 | }
149 | });
150 | } else {
151 | frappe.msgprint(__("First Select your NC Destination Folder"));
152 | }
153 | });
154 | }//,
155 | //btnClass: "hidden-xs"
156 | }
157 | ]
158 | }
159 |
160 |
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/folder_set/test_folder_set.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022, pibiCo and Contributors
2 | # See license.txt
3 |
4 | # import frappe
5 | import unittest
6 |
7 | class TestFolderSet(unittest.TestCase):
8 | pass
9 |
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/nextcloud_settings/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/pibidav/doctype/nextcloud_settings/__init__.py
--------------------------------------------------------------------------------
/pibidav/pibidav/doctype/nextcloud_settings/nextcloud_settings.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022, pibiCo and contributors
2 | // For license information, please see license.txt
3 |
4 | frappe.ui.form.on('NextCloud Settings', {
5 | refresh: function(frm) {
6 | if (frm.doc.nc_backup_enable && frm.doc.nc_backup_url && frm.doc.nc_backup_username && frm.doc.nc_backup_token) {
7 | // add check credentials button
8 | frm.add_custom_button(__("Check Credentials"), function() {
9 | frappe.call({
10 | method: "pibidav.pibidav.custom.check_nextcloud",
11 | args: {
12 | doc: frm.doc
13 | }
14 | });
15 | },__("NC Commands"));
16 | // add backup button
17 | frm.add_custom_button(__("Backup Now"), function() {
18 | frappe.call({
19 | method: "pibidav.pibidav.doctype.nextcloud_settings.nextcloud_settings.take_backup",
20 | freeze: true
21 | });
22 | }).addClass("btn-primary");
23 | }
24 | // Fill DocType Included with Data From Reference Item Table
25 | var includeArr = frm.doc.reference_item;
26 | var inclusion = '';
27 | for (var i=0; iInicio > pibiTools > pibiDAV
\",\"col\":12}},{\"id\":\"XQTScKtokJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Documents\",\"col\":4}},{\"id\":\"OIx7Apgo_M\",\"type\":\"card\",\"data\":{\"card_name\":\"Configuraci\u00f3n\",\"col\":4}}]",
4 | "creation": "2024-12-06 23:17:35.907677",
5 | "custom_blocks": [],
6 | "docstatus": 0,
7 | "doctype": "Workspace",
8 | "for_user": "",
9 | "hide_custom": 0,
10 | "icon": "pibidav",
11 | "idx": 0,
12 | "indicator_color": "",
13 | "is_hidden": 0,
14 | "label": "pibiDAV",
15 | "links": [
16 | {
17 | "hidden": 0,
18 | "is_query_report": 0,
19 | "label": "Documents",
20 | "link_count": 4,
21 | "link_type": "DocType",
22 | "onboard": 0,
23 | "type": "Card Break"
24 | },
25 | {
26 | "hidden": 0,
27 | "is_query_report": 0,
28 | "label": "pibiDAV Addon",
29 | "link_count": 0,
30 | "link_to": "PibiDAV Addon",
31 | "link_type": "DocType",
32 | "onboard": 0,
33 | "type": "Link"
34 | },
35 | {
36 | "hidden": 0,
37 | "is_query_report": 0,
38 | "label": "Tag",
39 | "link_count": 0,
40 | "link_to": "Tag",
41 | "link_type": "DocType",
42 | "onboard": 0,
43 | "type": "Link"
44 | },
45 | {
46 | "hidden": 0,
47 | "is_query_report": 0,
48 | "label": "Contact",
49 | "link_count": 0,
50 | "link_to": "Contact",
51 | "link_type": "DocType",
52 | "onboard": 0,
53 | "type": "Link"
54 | },
55 | {
56 | "hidden": 0,
57 | "is_query_report": 0,
58 | "label": "Event",
59 | "link_count": 0,
60 | "link_to": "Event",
61 | "link_type": "DocType",
62 | "onboard": 0,
63 | "type": "Link"
64 | },
65 | {
66 | "hidden": 0,
67 | "is_query_report": 0,
68 | "label": "Configuraci\u00f3n",
69 | "link_count": 3,
70 | "link_type": "DocType",
71 | "onboard": 0,
72 | "type": "Card Break"
73 | },
74 | {
75 | "hidden": 0,
76 | "is_query_report": 0,
77 | "label": "File Category",
78 | "link_count": 0,
79 | "link_to": "File Category",
80 | "link_type": "DocType",
81 | "onboard": 0,
82 | "type": "Link"
83 | },
84 | {
85 | "hidden": 0,
86 | "is_query_report": 0,
87 | "label": "NextCloud Settings",
88 | "link_count": 0,
89 | "link_to": "NextCloud Settings",
90 | "link_type": "DocType",
91 | "onboard": 0,
92 | "type": "Link"
93 | },
94 | {
95 | "hidden": 0,
96 | "is_query_report": 0,
97 | "label": "Folder Set",
98 | "link_count": 0,
99 | "link_to": "Folder Set",
100 | "link_type": "DocType",
101 | "onboard": 0,
102 | "type": "Link"
103 | }
104 | ],
105 | "modified": "2024-12-06 23:18:00.867514",
106 | "modified_by": "Administrator",
107 | "module": "Pibidav",
108 | "name": "pibiDAV",
109 | "number_cards": [],
110 | "owner": "Administrator",
111 | "parent_page": "pibiTools",
112 | "public": 1,
113 | "quick_lists": [],
114 | "roles": [
115 | {
116 | "role": "Docs Controller"
117 | },
118 | {
119 | "role": "Docs User"
120 | },
121 | {
122 | "role": "NextCloud User"
123 | }
124 | ],
125 | "sequence_id": 11.0,
126 | "shortcuts": [],
127 | "title": "pibiDAV"
128 | }
--------------------------------------------------------------------------------
/pibidav/pibidav/workspace/pibitools/pibitools.json:
--------------------------------------------------------------------------------
1 | {
2 | "charts": [],
3 | "content": "[{\"id\":\"w6ozBdED5x\",\"type\":\"header\",\"data\":{\"text\":\"Inicio > pibiTools
\",\"col\":12}},{\"id\":\"Xyxm-ti2im\",\"type\":\"custom_block\",\"data\":{\"custom_block_name\":\"AI Home\",\"col\":12}}]",
4 | "creation": "2024-12-06 23:53:55.428319",
5 | "custom_blocks": [],
6 | "docstatus": 0,
7 | "doctype": "Workspace",
8 | "for_user": "",
9 | "hide_custom": 0,
10 | "icon": "pibico",
11 | "idx": 0,
12 | "indicator_color": "",
13 | "is_hidden": 0,
14 | "label": "pibiTools",
15 | "links": [],
16 | "modified": "2024-12-07 10:10:19.730958",
17 | "modified_by": "Administrator",
18 | "module": "Pibidav",
19 | "name": "pibiTools",
20 | "number_cards": [],
21 | "owner": "Administrator",
22 | "parent_page": "",
23 | "public": 1,
24 | "quick_lists": [],
25 | "roles": [],
26 | "sequence_id": 3.0,
27 | "shortcuts": [],
28 | "title": "pibiTools"
29 | }
--------------------------------------------------------------------------------
/pibidav/public/dist/js/pibidav.bundle.VLVM6LDX.js:
--------------------------------------------------------------------------------
1 | (()=>{frappe.require?frappe.require("nc_browser.bundle.js"):frappe.ready(function(){frappe.require("nc_browser.bundle.js")});})();
2 | //# sourceMappingURL=pibidav.bundle.VLVM6LDX.js.map
3 |
--------------------------------------------------------------------------------
/pibidav/public/dist/js/pibidav.bundle.VLVM6LDX.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "sources": ["../../../../../apps/pibidav/pibidav/public/js/dist/nc_upload.js"],
4 | "sourcesContent": ["// Copyright (c) 2024, pibiCo and Contributors\n// MIT License. See license.txt\n\nif (frappe.require) {\n\tfrappe.require(\"nc_browser.bundle.js\");\n} else {\n\tfrappe.ready(function () {\n\t\tfrappe.require(\"nc_browser.bundle.js\");\n\t});\n}"],
5 | "mappings": "MAGI,OAAO,QACV,OAAO,QAAQ,sBAAsB,EAErC,OAAO,MAAM,UAAY,CACxB,OAAO,QAAQ,sBAAsB,CACtC,CAAC",
6 | "names": []
7 | }
8 |
--------------------------------------------------------------------------------
/pibidav/public/icons/timeless/icons.svg:
--------------------------------------------------------------------------------
1 |
33 |
--------------------------------------------------------------------------------
/pibidav/public/image/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/public/image/background.png
--------------------------------------------------------------------------------
/pibidav/public/image/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
91 |
--------------------------------------------------------------------------------
/pibidav/public/image/pibiCo_engine_largo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/public/image/pibiCo_engine_largo.png
--------------------------------------------------------------------------------
/pibidav/public/js/dist/nc_browser/NcBrowser.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ selected_node.value || '/' }}
5 |
6 |
10 |
14 |
15 |
16 |
17 | toggle_node(n)"
18 | @load-more="n => load_more(n)" />
19 |
20 |
21 |
22 |
23 |
264 |
265 |
--------------------------------------------------------------------------------
/pibidav/public/js/dist/nc_browser/TreeNode.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 | $emit('node-click', n)"
23 | @load-more="n => $emit('load-more', n)"
24 | />
25 |
33 |
34 |
35 |
36 |
37 |
60 |
61 |
--------------------------------------------------------------------------------
/pibidav/public/js/dist/nc_browser/nc_browser.bundle.js:
--------------------------------------------------------------------------------
1 | import { createApp, watch } from "vue";
2 | import NcBrowserComponent from './NcBrowser.vue';
3 |
4 | class Browser {
5 | constructor(options = {}) {
6 | const { wrapper, targetFolder, ...componentProps } = options;
7 | this.targetFolder = targetFolder;
8 | this.initializeWrapper(wrapper);
9 | this.initializeVueComponent({
10 | ...componentProps,
11 | root_folder: "/", // Set root folder to / for full navigation
12 | initial_folder: targetFolder // Set initial folder to target
13 | });
14 | }
15 |
16 | initializeWrapper(wrapper) {
17 | if (!wrapper) {
18 | this.make_dialog();
19 | } else {
20 | this.wrapper = wrapper.get ? wrapper.get(0) : wrapper;
21 | }
22 | }
23 |
24 | initializeVueComponent(props) {
25 | const app = createApp(NcBrowserComponent, {
26 | show_upload_button: !this.dialog,
27 | root_folder: "/", // Allow full navigation from root
28 | initial_folder: this.targetFolder, // Start at target folder
29 | ...props
30 | });
31 | this.browser = app.mount(this.wrapper);
32 | this.setupWatchers();
33 | }
34 |
35 | setupWatchers() {
36 | watch(
37 | () => this.browser.close_dialog,
38 | (close_dialog) => {
39 | if (close_dialog) this.dialog?.hide();
40 | }
41 | );
42 | }
43 |
44 | select_folder() {
45 | this.dialog?.get_primary_btn().prop('disabled', true);
46 | return this.browser.select_folder();
47 | }
48 |
49 | make_dialog() {
50 | this.dialog = new frappe.ui.Dialog({
51 | title: __('Select NextCloud Folder'),
52 | size: 'large',
53 | primary_action_label: __('Select'),
54 | primary_action: () => this.handlePrimaryAction()
55 | });
56 | this.wrapper = this.dialog.body;
57 |
58 | this.initializeVueComponent({
59 | show_browser: true,
60 | root_folder: "/", // Full navigation from root
61 | initial_folder: this.targetFolder // Start at target folder
62 | });
63 | this.dialog.show();
64 | this.setupDialogCleanup();
65 | }
66 |
67 | handlePrimaryAction() {
68 | const nc_folder = this.select_folder();
69 | const [doctype, docname] = this.getDocumentInfo();
70 | if (nc_folder.is_folder) {
71 | frappe.db.set_value("PibiDAV Addon", `pbc_${docname}`, {
72 | "nc_folder": nc_folder.path,
73 | "nc_enable": 1
74 | });
75 | } else {
76 | frappe.msgprint(__('You have selected a file and not a folder'), nc_folder.file_name);
77 | }
78 | this.dialog.hide();
79 | this.postSelectionAction(doctype);
80 | }
81 |
82 | getDocumentInfo() {
83 | const dtdn = this.wrapper.ownerDocument.body.getAttribute('data-route').replace('Form/', '');
84 | const pos = dtdn.lastIndexOf('/');
85 | const docname = dtdn.substr(pos + 1);
86 | const doctype = dtdn.replace('/' + docname, '');
87 | return [doctype, docname];
88 | }
89 |
90 | postSelectionAction(doctype) {
91 | if (doctype === 'Folder Set') {
92 | window.location.reload();
93 | } else {
94 | document.querySelector('.add-attachment-btn').click();
95 | }
96 | }
97 |
98 | setupDialogCleanup() {
99 | this.dialog.$wrapper.on('hidden.bs.modal', function() {
100 | $(this).data('bs.modal', null);
101 | $(this).remove();
102 | });
103 | }
104 | }
105 |
106 | frappe.provide("frappe.ui");
107 | frappe.ui.pibiDocs = Browser;
108 | export default Browser;
--------------------------------------------------------------------------------
/pibidav/public/js/dist/nc_pibidav.js:
--------------------------------------------------------------------------------
1 | frappe.ui.form.on(cur_frm.doctype, {
2 | refresh: function (frm) {
3 | if (!frm.doc.__islocal) {
4 | managePibiDAVAddon(frm);
5 | }
6 | },
7 | after_save: function (frm) {
8 | handleAfterSave(frm);
9 | }
10 | });
11 | // Function to manage PibiDAV Addon buttons and actions
12 | function managePibiDAVAddon(frm) {
13 | frappe.db.get_value(
14 | "PibiDAV Addon",
15 | { ref_doctype: frm.doc.doctype, ref_docname: frm.doc.name },
16 | ["nc_enable"]
17 | ).then(r => {
18 | const nc_enable = r.message?.nc_enable || 0;
19 | if (nc_enable !== 1) {
20 | addNextCloudEnableButton(frm);
21 | } else {
22 | addNextCloudButtons(frm);
23 | }
24 | });
25 | }
26 | // Add Enable NextCloud Button
27 | function addNextCloudEnableButton(frm) {
28 | frm.add_custom_button(frappe.utils.icon('nextcloud', 'md'), function () {
29 | handleEnableNextCloud(frm);
30 | })
31 | .addClass("btn btn-primary")
32 | .attr('title', __('Enable NextCloud'));
33 | }
34 | // Add Buttons for Upload, Check, and Disable NextCloud
35 | function addNextCloudButtons(frm) {
36 | frm.add_custom_button(__("Upload to NC"), function () {
37 | handleUploadToNextCloud(frm);
38 | }, __("NC"));
39 |
40 | frm.add_custom_button(__("Check Addon"), function () {
41 | handleCheckAddon(frm);
42 | }, __("NC"));
43 |
44 | frm.add_custom_button(frappe.utils.icon('nextcloud', 'md'), function () {
45 | handleDisableNextCloud(frm);
46 | })
47 | .addClass("btn btn-danger")
48 | .attr('title', __('Disable NextCloud'));
49 | }
50 | // Handle enabling NextCloud
51 | function handleEnableNextCloud(frm) {
52 | frappe.db.get_value(
53 | "PibiDAV Addon",
54 | { ref_doctype: frm.doc.doctype, ref_docname: frm.doc.name },
55 | ["name", "nc_folder", "nc_enable"]
56 | ).then(r => {
57 | const addon = r.message || {};
58 |
59 | if (!addon.name) {
60 | // Addon does not exist, create it first
61 | createAddon(frm, (newAddon) => {
62 | processNextCloudEnable(frm, newAddon);
63 | });
64 | } else {
65 | // Addon exists, proceed to process enabling
66 | processNextCloudEnable(frm, addon);
67 | }
68 | });
69 | }
70 | // Process enabling NextCloud
71 | function processNextCloudEnable(frm, addon) {
72 | const nc_parent_folder = frm.doc.nc_parent_folder;
73 |
74 | if (nc_parent_folder) {
75 | frappe.db.set_value("PibiDAV Addon", addon.name, {
76 | nc_enable: 1,
77 | nc_folder_internal_link: nc_parent_folder
78 | }).then(() => {
79 | fetchAndSetFolderPath(nc_parent_folder, addon.name, frm);
80 | });
81 | } else {
82 | frappe.db.set_value("PibiDAV Addon", addon.name, { nc_enable: 1 })
83 | .then(() => location.reload());
84 | }
85 | }
86 | // Handle uploading to NextCloud
87 | function handleUploadToNextCloud(frm) {
88 | frappe.db.get_value(
89 | "PibiDAV Addon",
90 | { ref_doctype: frm.doc.doctype, ref_docname: frm.doc.name },
91 | ["name", "nc_folder", "nc_folder_internal_link"]
92 | ).then(r => {
93 | const addon = r.message || {};
94 | if (addon.name) {
95 | openNextCloudBrowser(addon);
96 | } else {
97 | createAddon(frm, () => openNextCloudBrowser({}));
98 | }
99 | });
100 | }
101 | // Handle checking the Addon
102 | function handleCheckAddon(frm) {
103 | frappe.db.get_value(
104 | "PibiDAV Addon",
105 | { ref_doctype: frm.doc.doctype, ref_docname: frm.doc.name },
106 | ["name"]
107 | ).then(r => {
108 | const addon = r.message || {};
109 | if (addon.name) {
110 | frappe.set_route("Form", "PibiDAV Addon", addon.name);
111 | } else {
112 | createAddon(frm, pibidav => {
113 | frappe.set_route("Form", "PibiDAV Addon", pibidav.name);
114 | });
115 | }
116 | });
117 | }
118 | // Handle disabling NextCloud
119 | function handleDisableNextCloud(frm) {
120 | frappe.db.set_value("PibiDAV Addon", `pbc_${frm.doc.name}`, { nc_enable: 0 })
121 | .then(() => location.reload());
122 | }
123 | // Create or Update Addon with Folder
124 | function createOrUpdateAddonWithFolder(frm, addon) {
125 | const docname = frm.doc.name;
126 | const nc_parent_folder = frm.doc.nc_parent_folder;
127 | const addonName = addon.name || `pbc_${docname}`;
128 |
129 | frappe.db.set_value("PibiDAV Addon", addonName, {
130 | nc_enable: 1,
131 | nc_folder_internal_link: nc_parent_folder
132 | }).then(() => {
133 | fetchAndSetFolderPath(nc_parent_folder, addonName);
134 | });
135 | }
136 | // Create or Update Addon without Folder
137 | function createOrUpdateAddonWithoutFolder(frm, addon) {
138 | const docname = frm.doc.name;
139 | const addonName = addon.name || `pbc_${docname}`;
140 |
141 | frappe.db.set_value("PibiDAV Addon", addonName, { nc_enable: 1 })
142 | .then(() => location.reload());
143 | }
144 | // Fetch and Set Folder Path
145 | function fetchAndSetFolderPath(folderLink, addonName) {
146 | frappe.db.get_value("PibiDAV Addon", addonName, "nc_folder").then(result => {
147 | const currentFolder = result.message.nc_folder;
148 |
149 | // Check if nc_folder is already filled
150 | if (currentFolder && currentFolder.trim() !== "") {
151 | console.log(__('Folder path is already set. No changes made.'));
152 | location.reload();
153 | } else {
154 | // If not filled, proceed to fetch and set the folder path
155 | frappe.call({
156 | method: 'pibidav.pibidav.custom.get_folder_path_from_link',
157 | args: { fileid: extractFileId(folderLink) },
158 | callback: function (r) {
159 | if (!r.exc) {
160 | frappe.db.set_value("PibiDAV Addon", addonName, {
161 | nc_folder: r.message
162 | }).then(() => location.reload());
163 | } else {
164 | frappe.msgprint(__('Failed to fetch folder path.'));
165 | location.reload();
166 | }
167 | }
168 | });
169 | }
170 | });
171 | }
172 | // Open NextCloud Browser
173 | function openNextCloudBrowser(addon) {
174 | const targetFolder = addon.nc_folder || '/'; // Start at root if no folder is configured
175 |
176 | new frappe.ui.pibiDocs({
177 | targetFolder: targetFolder,
178 | root_folder: targetFolder
179 | });
180 | }
181 | // Create Addon
182 | function createAddon(frm, callback) {
183 | frappe.db.insert({
184 | doctype: "PibiDAV Addon",
185 | ref_doctype: frm.doc.doctype,
186 | ref_docname: frm.doc.name,
187 | nc_enable: 1
188 | }).then(callback);
189 | }
190 | // Handle After Save
191 | function handleAfterSave(frm) {
192 | frappe.db.get_list("PibiDAV Addon", {
193 | filters: { ref_doctype: frm.doc.doctype, ref_docname: frm.doc.name },
194 | fields: ["nc_enable", "nc_folder_internal_link"]
195 | }).then(res => {
196 | const addon = res[0] || {};
197 | if (!addon.nc_folder_internal_link && addon.nc_enable) {
198 | createFolderDialog(frm);
199 | }
200 | });
201 | }
202 | // Create Folder Dialog
203 | function createFolderDialog(frm) {
204 | frappe.call({
205 | method: "pibidav.pibidav.custom.doCreateFolder",
206 | args: { doctype: frm.doc.doctype }
207 | }).then(r => {
208 | if (r.message) {
209 | openFolderCreationDialog(frm, r.message);
210 | }
211 | });
212 | }
213 | // Open Folder Creation Dialog
214 | function openFolderCreationDialog(frm, doCreate) {
215 | const defaultData = getDefaultFolderData(frm);
216 | if (doCreate) {
217 | const d = new frappe.ui.Dialog({
218 | title: __('Create NC Folder'),
219 | fields: getFolderDialogFields(defaultData),
220 | primary_action_label: 'Create',
221 | primary_action(values) {
222 | if (!values.abbreviation || !values.strmain || !values.folder_set) {
223 | frappe.throw(__('Complete all data: Abbreviation, Folder Name, and Folder Set'));
224 | }
225 | createNextCloudFolder(frm, values);
226 | d.hide();
227 | }
228 | });
229 | d.show();
230 | }
231 | }
232 | // Utility Functions
233 | function extractFileId(htmlString) {
234 | const regex = /\/f\/(\d+)/;
235 | const match = htmlString.match(regex);
236 | return match ? match[1] : null;
237 | }
238 | //
239 | function getDefaultFolderData(frm) {
240 | if (frm.doc.doctype === 'Customer') {
241 | return {
242 | folder_name: frm.doc.customer_name,
243 | abbreviation: frm.doc.pb_abbreviation,
244 | folder_set: '(CLI) Plantilla Clientes'
245 | };
246 | } else if (frm.doc.doctype === 'Supplier') {
247 | return {
248 | folder_name: frm.doc.supplier_name,
249 | abbreviation: frm.doc.pb_abbreviation,
250 | folder_set: '(PRO) Plantilla Proveedores'
251 | };
252 | }
253 | return {};
254 | }
255 | //
256 | function getFolderDialogFields(defaultData) {
257 | return [
258 | { label: __('Enter Abbreviation'), fieldname: 'abbreviation', fieldtype: 'Data', default: defaultData.abbreviation },
259 | { label: __('Enter Folder Name'), fieldname: 'strmain', fieldtype: 'Data', default: defaultData.folder_name },
260 | { label: __('Select Folder Set'), fieldname: 'folder_set', fieldtype: 'Link', options: 'Folder Set', filters: { parent_folder_set: '' }, default: defaultData.folder_set },
261 | { label: __('Sharing Option'), fieldname: 'sharing_option', fieldtype: 'Select', options: ['', '4-Upload Only', '17-Read Only', '31-Upload and Edit'] },
262 | { label: __('Sharing Password'), fieldname: 'secret', fieldtype: 'Data' }
263 | ];
264 | }
265 | //
266 | function createNextCloudFolder(frm, values) {
267 | frappe.call({
268 | method: "pibidav.pibidav.custom.create_nc_folder",
269 | args: {
270 | dt: frm.doc.doctype,
271 | dn: frm.doc.name,
272 | abbr: values.abbreviation,
273 | strmain: values.strmain,
274 | folder_set: values.folder_set,
275 | sharing_option: values.sharing_option,
276 | secret: values.secret || ""
277 | }
278 | }).then(r => {
279 | frappe.msgprint(r.message);
280 | });
281 | }
--------------------------------------------------------------------------------
/pibidav/public/js/dist/nc_upload.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2024, pibiCo and Contributors
2 | // MIT License. See license.txt
3 |
4 | if (frappe.require) {
5 | frappe.require("nc_browser.bundle.js");
6 | } else {
7 | frappe.ready(function () {
8 | frappe.require("nc_browser.bundle.js");
9 | });
10 | }
--------------------------------------------------------------------------------
/pibidav/public/js/pibidav.bundle.js:
--------------------------------------------------------------------------------
1 | // public/js/pibidav.bundle.js
2 |
3 | import './dist/nc_upload.js';
--------------------------------------------------------------------------------
/pibidav/templates/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/templates/__init__.py
--------------------------------------------------------------------------------
/pibidav/templates/pages/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/templates/pages/__init__.py
--------------------------------------------------------------------------------
/pibidav/translations/es.csv:
--------------------------------------------------------------------------------
1 | 17-Read Only,17-Solo Lectura
2 | 31-Upload and Edit,31-Subida y Edición
3 | 4-Upload Only,4-Subida Unicamente
4 | Abbreviation,Abreviatura
5 | About,Acerca de
6 | About Us Settings,Ajustes Página Acerca de
7 | Accounting,Financiero
8 | "Accounts, Invoices, Taxation, and more.","Cuentas, Facturas, Tasas y más."
9 | Action If Same Rate is Not Maintained,Acción si no se mantiene la misma Tasa
10 | Active,Activo
11 | Activity Type,Identificación Actividad
12 | Add / Remove Columns,Añade / Elimina Columnas
13 | Add a Filter,Añade Filtro
14 | Add Blog Category,Añadir Categoria de Blog
15 | Add Tags,Añade Etiquetas
16 | AI Extract,Extraído IA
17 | Alert Channels,Canales de Alerta
18 | Alert Date,Fecha de Alerta
19 | Alert Gap,Intervalo sin Alerta
20 | Alert Log,Registro de Alertas
21 | Alert Threshold,Umbrales de Alerta
22 | Alerts Active,Alertas Activas
23 | Alerts Received,Alertas Recibidas
24 | Answered,Respondido a Cliente
25 | Apply Filters,Aplicar Filtros
26 | Assets,Bienes/Activos
27 | "Assets, Depreciations, Repairs, and more.","Activos, Depreciaciones, Reparaciones y más."
28 | Assigned,Asignado
29 | Assistant Section,Asistente
30 | Attachment Files,Ficheros Adjuntos
31 | Attachment Item,Ficheros Controlados
32 | Attended,Asistió
33 | Backup Now,Respaldo Ahora
34 | Backup public and private files along with the database and site config,"Respaldo con base de datos, archivos públicos, privados y site_config.json"
35 | Bank Reconciliation Tool,Herramienta de Reconciliación Bancaria
36 | Bill for Rejected Quantity in Purchase Invoice,Factura por cantidad rechazada en la Factura de Compra
37 | Birthdays,Cumpleaños
38 | Blanket Order,Pedido Marco
39 | Blogger,Bloguero
40 | "Blogs, Website View Tracking, and more.","Blogs, Seguimiento de Vistas Web y más."
41 | BOM,LdM
42 | Box,Caja
43 | Build,Desarrollador
44 | by Email,Por Email
45 | by SMS,por SMS
46 | CalDav Calendar,Calendario CalDav
47 | CalDav ID Calendar,Calendario CalDav
48 | CalDav ID URL,ID URL CalDav
49 | Calendar,Calendario
50 | Can Submit,Puede Validar
51 | Cash Flow Statement,Estado de Tesorería
52 | Chairperson,Presidente
53 | Change Abbreviation,Cambiar Abreviatura
54 | Channels,Canales
55 | Chart of Accounts,Plan Contable
56 | Check Addon,Extensión NC
57 | Check Credentials,Comprueba Credenciales
58 | Check Stock Projected Qty,Comprobar la Cantidad de Estocaje Proyectado
59 | Child Data,Datos de Tabla
60 | Child Selector,Selector de Tablas
61 | Column Width,Ancho de Columna
62 | Commented,Comentado por Cliente
63 | Comments Closed,Comentarios Cerrados
64 | Committed Date,Fecha Contrato Proveedor
65 | Communication Date,Fecha Comunicación
66 | Company Fax,Fax Empresa
67 | Company Phone,Teléfono Empresa
68 | Company Website,Web Empresa
69 | "Complete all data Abbreviation, Folder Name and Folder Set","Completa la abreviatura, el nombre de carpeta y la plantilla"
70 | Complete by,Completar el
71 | Configure Account Settings,Configura los Ajustes de Finanzas
72 | Configure Buying Settings.,Configurar los Ajustes de Compras.
73 | Configure Columns,Configurar Columnas
74 | Configure Selling Settings.,Configurar los Ajustes de Ventas.
75 | Configure the action to stop the transaction or just warn if the same rate is not maintained.,Configurar la transacción de paro o sólo advertir de que no se mantiene la misma tasa
76 | Confirm action,Confirma la acción
77 | Connections,Conexiones
78 | Consequent Event,Evento Consecuente
79 | Content Phase,Fase de Creación de Contenido
80 | Contract Number,Numero Contrato
81 | Copy to Clipboard,Copiar al Portapapeles
82 | Create,Crear
83 | Create a Customer,Crear un Cliente
84 | Create a Fixed Asset Item,Crear un Artículo de Activo Fijo
85 | Create a Material Request,Crear una Solicitud de Material
86 | Create a Material Transfer Entry,Crear una Entrada de Transferencia de Material
87 | Create a Product,Crear un Producto
88 | Create a Quotation,Crear una Oferta
89 | Create a Supplier,Crear un Proveedor
90 | Create an Asset,Crear un Activo
91 | Create an Asset Category,Crear una Categoría de Activos
92 | Create and Send Quotation,Crear y Enviar Oferta
93 | Create Blogger,Crear Bloguero
94 | Create Department,Crear Departamento
95 | Create Designation,Crear Puesto
96 | Create Entry,Crear Entrada
97 | Create Holiday List,Crear Listado de Vacaciones
98 | Create in NC,Crear en NC
99 | Create Income Tax Slab,Crear Tabla IRPF
100 | Create Lead,Crear Iniciativa
101 | Create Leave Allocation,Crear Solicitud de Ausencia
102 | Create Leave Application,Crear Peticion de Ausencia
103 | Create Leave Type,Crear Tipo de Ausencia
104 | Create NC Folder,Crear Carpeta NC
105 | Create NC Group,Crear Grupo NC
106 | Create Opportunity,Crear Oportunidad
107 | Create Payroll Period,Crear Período de Nómina
108 | Create Salary Component,Crear Componente Salarial
109 | Create Salary Structure,Crear Estructura Salarial
110 | Create Your First Purchase Invoice ,Crear la primera Factura de Venta
111 | Create your first Purchase Order,Crear tu primera Orden de Compra
112 | Create Your First Sales Invoice ,Crear la primera Factura de Venta
113 | Create your first Sales Order,Crear tu primer Pedido de Venta
114 | Customer Comments,Comentarios Cliente
115 | Customer Date,Fecha Contractual Cliente
116 | Customer name,Denominación Cliente
117 | Customer Number,Numero Cliente
118 | Customer Penalty,Penalizado Cliente
119 | Customer Submission,Fecha Entrega Cliente
120 | Customer Updated,Fecha Actualizada Cliente
121 | Customer Weight,Peso Cliente
122 | Dashboard,Panel Control
123 | Data Import,Importación de Datos
124 | Default In-Transit Warehouse,Almacén en Tránsito por Defecto
125 | Deleted Event in CalDav,Borrado Evento en CalDav
126 | Deleted Event in CalDav Calendar,Borrado el Evento en Calendario CalDav
127 | Deliver To,Transmitir A
128 | Deliverable,Entregable
129 | Deliverable Type,Tipo Entregable
130 | Deliverables,Entregables
131 | Deliverables & Settings,Entregables
132 | Delivery Item,Documentos Entrega
133 | Delivery Note,Albaran
134 | Delivery Purpose,Propósito de Envío
135 | Digits to substitute with abbreviation,Digitos Plantilla a sustituir con Abreviatura
136 | Disable NC,Desactiva NC
137 | Disable NextCloud,Desactiva NextCloud
138 | Discipline,Especialidad
139 | Dispatch Address Name,Dirección de Entrega
140 | Distribution,Distribución
141 | Do you want to save empty doc to prompt?,Quieres gravar primero para ejecutar prompts?
142 | "DocField Names selected for tagging, comma separated without spaces","Nombre de campo elegido para etiquetado, separado por comas y sin espacios"
143 | DocFields to use from selected DocType separated by commas without spaces,Cadena de DocFields del DocType elegido a usar separados por comas y sin espacios
144 | Docs Controller,Control Documentacion
145 | Docs User,Usuario Documentacion
146 | DocType Selection,Selección de DocTypes
147 | DocType Selector,Selector DocTypes
148 | Document Number,Numero Documento
149 | Document Responsible,Responsable del Documento
150 | Document Submission,Transmisión de Documento
151 | Documentation,Documentación
152 | Documents,Documentos
153 | Drag and drop files here or upload from,Arrastra y suelta los archivos aquí o súbelos desde
154 | Due to MicroTemplating never use ' simple quotes in the html code.,Debido al uso de MicroTemplates nunca use comillas simples en el código html
155 | Edit Filters,Editar Filtros
156 | Edition,Edición
157 | Email alert,Alerta por Email
158 | Email Recipients,Receptores Email
159 | Employee Grievance,Queja de Empleado
160 | Employee Onboarding,Oferta de Empleo
161 | Employee Records to be created by,Los registros de Empleados se crean por
162 | "Employee, Leaves, and more.","Empleado, Ausencias y más"
163 | Employees Working on a Holiday,Empleados trabajando en festivo
164 | Enable NC,Activa NC
165 | Enable Website Tracking,Activar Seguimiento Web
166 | Enable NextCloud,Activa NextCloud
167 | Enter Abbreviation,Introduce la Abreviatura
168 | Enter Folder Name,Introduce el Nombre de Carpeta
169 | Error Creating NC Group,Error creando Grupo en NC
170 | Event created successfully.,Evento creado satisfactoriamente.
171 | Event removed successfully.,Evento eliminado correctamente.
172 | Event Stamp,Sello Evento
173 | Event UID,UID Evento
174 | Event updated successfully.,Evento actualizado correctamente.
175 | "Exact DocType Name wihout quotes, whithout spaces and separated by comma (i.e. Sales Invoice,Purchase Order)",Nombre de DocType Exacto sin espacios y separado por comas
176 | Feed Data,Datos a Alimentar
177 | Feeding Section,Sección Asistencia
178 | Fields to Tag,Campos para Etiquetado
179 | File Category,Categoría Archivado
180 | File List,Lista Archivos
181 | File Structure,Estructuras Carpetas
182 | Filename,Nombre Archivo
183 | filter,filtro
184 | Finally Approved,Aprobado Cliente
185 | First Select your NC Destination Folder,Primero Selecciona tu Carpeta Destino NC
186 | Fixed Asset Defaults,Configuración de Activos
187 | Folder Path,Ruta de Carpeta
188 | Folder Set,Plantillas Carpetas
189 | Follow Up Process,Seguimiento
190 | Free,Libre
191 | From Opportunity,Desde Oportunidad
192 | Generate Vcard Book,Generar Libro de Contactos
193 | Go to Page,Ir a la Página
194 | GPT Response,Respuesta GPT
195 | Grievance Type,Tipo de Queja
196 | Hero with Right Image,Heroe con Imagen a la Derecha
197 | Hour,Hora
198 | HR Settings,Configuración de RRHH
199 | HTML Code,Código HTML
200 | ID Number,Número ID
201 | "If checked, Rejected Quantity will be included while making Purchase Invoice from Purchase Receipt.","Si se marca, la cantidad rechazada será incluida al hacerse la factura de Compra desde el Albarán de Compra."
202 | Import .eml,Importar .eml
203 | Import .msg,Importar .msg
204 | Import vCard,Importar vCard
205 | Importing Contacts,Importando Contactos
206 | Inclusions,Inclusiones
207 | Integrate vCard Book,Integrar libro vCard
208 | Internal Comments,Comentarios Internos
209 | Introduction to Assets,Introducción a los Activos
210 | Introduction to Buying,Introducción a Compras
211 | Introduction to CRM,Introducción al CRM
212 | Introduction to Selling,Introducción a Ventas
213 | Introduction to Website,Introducción al Sitio Web
214 | "Inventory, Warehouses, Analysis, and more.","Inventario, Almacenamientos, Análisis y Más"
215 | Invitation Accepted,Invitación Aceptada
216 | Invitations,Invitaciones
217 | is Group,es Carpeta
218 | Is HTML,es HTML
219 | Is SuperStructure,Es Superestructura
220 | Is Translation,Es Traducción?
221 | Issuer Native,Edición Nativa
222 | Item,Producto
223 | Item Name,Nombre del Producto
224 | Language,Idioma
225 | Last Seen,Ultima Actividad
226 | "Lead, Opportunity, Customer, and more.","Iniciativa, Oportunidad, Cliente y más."
227 | Leaderboard,Cuadro de Honor
228 | Learn about Web Pages,Aprender sobre Páginas Web
229 | Leave Application,Petición de Ausencia
230 | Let's Set Up the Assets Module.,Configurar el Módulo de Activos.
231 | Let's Set Up the Buying Module.,Configuremos el Módulo de Compras
232 | Let's Set Up the Human Resource Module.,Configuremos el módulo de RRHH
233 | Let's Set Up the Payroll Module.,Configurar el Módulo de Nómina
234 | Let's Set Up the Selling Module.,Configuremos el Módulo de Ventas.
235 | Let's Set Up the Stock Module.,Configuremos el Módulo de Productos
236 | Let's Set Up Your Accounts and Taxes.,Configuremos Cuentas e Impuestos
237 | Let's Set Up Your CRM.,Configurar el CRM
238 | Let's Set Up Your Website.,Configuremos su Sitio Web
239 | Let’s create a stock opening entry,Creemos una entrada de apertura de stock
240 | Let’s create your first warehouse ,Creemos tu primer almacen
241 | Lets create a Tax Template for Sales ,Crear una Plantilla de Impuestos en Ventas
242 | Library,Biblioteca
243 | LifeCycle Status,Ciclo de Vida
244 | Like,Contiene
245 | List,Lista
246 | List of DocFields separated by commas without spaces to produce automatic file tagging in FP and NC,Lista de DocField separados por comas y sin espacios para asignar etiquetas automáticas en FP y NC a los archivos
247 | List View,Vista Lista
248 | Lists,Listados
249 | Location,Localización
250 | Lower Value,Valor Inferior
251 | Mail Signature,Firma de Correo
252 | Make a Sales Tax Template,Crear una plantilla de Impuestos en Ventas
253 | Manage eMails,Gestión eMails
254 | Manage Stock Movements,Gestionar movimientos de Artículos
255 | Masters,Maestros
256 | Minute of Meeting,Acta de Reunión
257 | Minutes Section,Registros/Actas
258 | Modules,Módulos
259 | Month,Mes
260 | MQTT Settings,Ajustes MQTT
261 | My Device,Mi Equipo
262 | My Profile,Mi Perfil
263 | My Settings,Mis Ajustes
264 | Name,ID
265 | name,ID
266 | Native,Original Nativo
267 | Native Files,Archivos Originales
268 | Native multipart,Multiparte nativo
269 | Native pdf,pdf Nativo
270 | NC Commands,Ordenes NC
271 | NC Doctypes Excluded,DocTypes Excluidos de NC
272 | NC Doctypes Included,DocTypes incluidos para NC
273 | NC Enable,Activa NC
274 | NC File List,Lista Archivos NC
275 | NC File Upload,Subir Archivos a NC
276 | NC Folder,Carpeta NC
277 | NC Folder Creation,Creación de Carpetas en NC
278 | NC Folder Internal Link,Enlace Interno Carpeta NC
279 | NC Folder Share Link,Enlace Compartido Carpeta NC
280 | NC Group Already Exists,Grupo NC ya Existe
281 | NC Group Created,Grupo NC Creado
282 | NC Path,Ruta NC
283 | NC Private Link,Enlace privado NC
284 | NC Share Link,Enlace Compartido NC
285 | New Chart,Nuevo Gráfico
286 | New Shortcut,Nuevo Atajo
287 | NextCloud Backup Credentials,Credenciales NextCloud Backup
288 | NextCloud Backup Enable,Activa NextCloud Backup
289 | NextCloud Credentials,Credenciales NextCloud
290 | NextCloud Credentials are correct,Credenciales NC correctas
291 | NextCloud Settings,Ajustes NextCloud
292 | No contacts selected.,No hay contactos seleccionados.
293 | No message associated,No hay asociado ningún mensaje
294 | Non Participant,No Participante
295 | OCR Extract,Extraído OCR
296 | OCR Extraction in progress,Extracción OCR en ejecución
297 | Off From Time,Fuera Desde
298 | Off To Time,Fuera Hasta
299 | Only one recipient can be provided,Solo se puede proporcionar un destinatario
300 | Optional,Opcional
301 | Overview,Información General
302 | Page Title,Título de Página
303 | Parent File Structure,Nodo Padre
304 | Parent Folder,Carpeta Padre
305 | Parent Path,Ruta Padre
306 | Parties,Participantes
307 | Pending Close,Comentarios pendientes cierre
308 | Phase,Fase
309 | Please provide a proper prompt,Por favor proporciona un prompt adecuado
310 | PO Name,Denominación Orden Compra
311 | prepare eMail,Preparar eMail
312 | Print Language,Idioma de Impresión
313 | Production Phase,Fase de Producción
314 | Production Unit,Unidad Producida
315 | "Products, Purchases, Analysis, and more.","Productos, Compras, Análisis y más"
316 | Profile,Perfil
317 | Published,Publicado
318 | Purchase an Asset Item,Comprar un Activo
319 | Purchase Receipt,Albarán de Compra
320 | QR Key,Llavero RFID/QR
321 | QR Keys,Llaveros RFID
322 | QRKey,Llave RFID/QR
323 | Qualification Stamp,Sello Calificación
324 | Queued for Backup. It may take a long time depending on your backup files size. Rest Easy!!!,Copia de Respaldo en cola. Puede llevar mucho tiempo dependiendo del tamaño de los archivos
325 | Quick Access,Acceso Rápido
326 | Quotation,Oferta
327 | Rate per Minute,Tasa por minuto
328 | Raw File,Archivo Fuente
329 | Rebuild Tree,Reconstruir Árbol
330 | Recipient,Destinatario
331 | Recreate,Recrea
332 | Recreate Folders in NC,Recrea las carpetas en NC
333 | Refresh Files List,Refrescar Indice NC
334 | Reminders,Recordatorios
335 | Rendered HTML,HTML
336 | Report,Informe
337 | Report an Issue,Informar de una Incidencia
338 | Report View,Vista Informe
339 | Reports & Masters,Informes y Maestros
340 | Request for Quotation,Petición de Oferta
341 | Required,Requerido
342 | Reset Customizations,Eliminar Personalizaciones
343 | Reset to default,Resetear por Defecto
344 | Restrict Backdated Leave Application ,Restringir Solicitudes de Vacaciones Retroactivas
345 | Retail,Al por menor
346 | Retirement Age,Edad de Jubilación
347 | Review Chart of Accounts,Revisar Plan Contable
348 | Review Process,Proceso de Revision
349 | Review Stock Settings,Revisar los Ajustes de Productos
350 | RFI Answer,Respuesta Solicitud Información
351 | RFI Answered,Solicitud Información Respondida
352 | RFI Closed,Solicitud de Información Cerrada
353 | RFI Pending,Solicitud Informacion Pendiente
354 | RFI Request,Solicitud Informacion
355 | RFID Tag,Control Llaves Tag
356 | Role Allowed to Override Stop Action,Rol permitido para sobreescribir Acción de Paro
357 | Root Dir Name,Nombre Directorio Raiz
358 | "Salary, Compensation, and more.","Salrios, Compensaciones y más"
359 | Sales Order,Pedido de Venta
360 | Save Customizations,Guardar Personalizaciones
361 | Secret,Clave
362 | Seed,Germen
363 | Select NC Folder,Elige Carpeta NC
364 | Select NextCloud Destination Folder,Elige la carpeta de destino en NextCloud
365 | Select NextCloud Folder,Elige la carpeta de destino en NextCloud
366 | Send Email,Enviar Correo
367 | Select Folder Set,Elige la Plantilla de Carpeta
368 | Send Invitation,Enviar Invitación
369 | Send Leave Notification,Enviar Notificación de Ausente
370 | Sensor Log,Registro de Sensores
371 | Sensor Readings,Lecturas de Sensor
372 | Sent Or Received,Enviado o Recibido
373 | Serial,N.Serie
374 | Set all private,Establecer todos privados
375 | Set all public,Establecer todos públicos
376 | Set the frequency for holiday reminders,Establecer la frecuencia de los recordatorios de Vacaciones
377 | Set up your Warehouse,Configurar tu Almacenamiento
378 | Settings Section,Sección de Ajustes
379 | Setup a Warehouse,Configurar un Almacenamiento
380 | Share Link,Enlace Compartido
381 | Share URL,Comparte URL
382 | Sharing Option,Opción Compartir
383 | Sharing Password,Clave Compartición
384 | Sharing password must be greater than 10 chars long and not usual,La clave de compartición debe ser mayor de 10 caracteres y no comun
385 | Shipping Address Name,Dirección de Despacho
386 | Shortener,Recorte
387 | Show Form Tour,Mostrar un Tour en Formulario
388 | Show Preview,Previsualización
389 | Show Saved,Mostrar Guardados
390 | Signature Item,Firmas de Correo
391 | Signature Picture,Imagen Firma
392 | SMS alert,Alerta por SMS
393 | SMS Recipients,Receptores SMS
394 | Source Lang,Idioma Origen
395 | Spain,España
396 | Standard with Numbers,Estándar con Numeración
397 | Standard Working Hours,Horas de Trabajo Normales
398 | Start and End Dates,Control Actividad
399 | Stock,Productos
400 | Submitted,Transmitido
401 | Summarization,Sumarización
402 | Superseeded,Superado
403 | Supplier Attachments,Archivos de Proveedor
404 | Supplier Delivery,Fecha Entrega Proveedor
405 | Supplier Number,Numero Proveedor
406 | Supplier Penalty,Penalizado Proveedor
407 | Supplier Weight,Peso Proveedor
408 | Sure you want to ask chatGPT?,Seguro de preguntar a chatGPT
409 | Sync with CalDav,Sincronizar con CalDav
410 | Synchronization successful.,Sincronización correcta.
411 | System User,Usuario del Sistema
412 | Take a walk through Stock Settings,Dar un paseo por los Ajustes de Productos
413 | Target Lang,Idioma Destino
414 | Team Members Subtitle,Subtítulos Miembros del Equipo
415 | This is based on Alerts received from this Sensor,Mapa basado en Alertas recibidas desde este Sensor
416 | Timesheet,Parte de Trabajo
417 | to Customer,Envio a Cliente
418 | To Customer,A Cliente
419 | to External,Envio a Terceros
420 | To ReIssue,A reeditar
421 | To Review,A Revisar
422 | Toggle Full Width,Alterna Vista Completa
423 | Toggle Theme,Ajustar Aspecto
424 | Tools,Herramientas
425 | Transaction Feed,Alimentar Transacción
426 | Transcription Language,Idioma Destino
427 | Tree,Árbol
428 | Unit of Measure (UOM),Unidad de Medida (UdM)
429 | UOM,UdM
430 | Update Settings,Actualizar Ajustes
431 | Update Stock Opening Balance,Actualizar el Balance de Apertura de Estocaje
432 | Updated Date,Fecha actualizada Proveedor
433 | Updated/Created Event in Calendar,Actualizado/Creado un Evento de Calendario
434 | Upload to NC,Subir a NC
435 | Upload to NextCloud,Subir a NextCloud
436 | Uploaded To NC,Subido a NC
437 | Uploaded To NextCloud,Subido a NextCloud
438 | Upper Value,Valor Superior
439 | User Forum,Foro de Usuarios
440 | User Prompt,Prompt de Usuario
441 | Validated,Validado
442 | vCard Create,Crear vCard
443 | vCard Download,Descargar vCard
444 | vCard Integration,Integración vCard
445 | vCard QR Code,Código QR vCard
446 | vCard Text,Texto vCard
447 | Vendor,Proveedor
448 | Watch Tutorial,Ver el Tutorial
449 | Watch Video,Mirar el Video
450 | Web Page,Página Web
451 | Work Anniversaries ,Aniversarios de Trabajo
452 | Work Place,Area de Control
453 | WorkCenter,Area de Control
454 | WorkCenter Occupancy,Ocupacion Area
455 | WorkCenter Schedule,Horario Area
456 | Workship,Area de Control
457 | Workship Occupancy,Ocupación de Área
458 | Workship Schedule,Horario Area
459 | You can only reply to one message at a time,Sólo puedes responder a un mensaje de cada vez
460 | You have selected a file and not a folder,Se ha seleccionado un archivo y no una carpeta
461 | You must select one message,Debes elegir un mensaje
462 | NC Folder Link,Enlace Carpeta NC
463 | Fetch NC Folder Link,Obtener Enlace Carpeta NC
464 |
--------------------------------------------------------------------------------
/pibidav/www/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pibico/pibiDAV/660caffafd274f1dcf6c42024d5f67bccd5c8509/pibidav/www/__init__.py
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # frappe -- https://github.com/frappe/frappe is installed via 'bench init'
2 | frappe
3 | payments
4 | erpnext
5 | hrms
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | with open("requirements.txt") as f:
4 | install_requires = f.read().strip().split("\n")
5 |
6 | # get version from __version__ variable in pibidav/__init__.py
7 | from pibidav import __version__ as version
8 |
9 | setup(
10 | name="pibidav",
11 | version=version,
12 | description="WebDAV, CalDAV and CardDAV Integration between Frappe and NextCloud",
13 | author="pibiCo",
14 | author_email="pibico.sl@gmail.com",
15 | packages=find_packages(),
16 | zip_safe=False,
17 | include_package_data=True,
18 | install_requires=install_requires
19 | )
20 |
--------------------------------------------------------------------------------