ContentEditHeader.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. <template>
  2. <div class="entity-edit-header">
  3. <div v-if="selectedValues.length > 0">
  4. <q-card class="upper-card bg-primary flex items-center q-pa-md">
  5. <div class="base-part flex items-center">
  6. <div class="header-item">
  7. {{ selectedValues.length }} مورد انتخاب شده
  8. </div>
  9. <div class="line header-item" />
  10. </div>
  11. <div v-if="isInEditMode"
  12. class="edit-mode flex items-center justify-between">
  13. <div class="header-item">در حال ویرایش {{editSelectorValue.label}}</div>
  14. <div class="action-btn flex items-center">
  15. <div>
  16. <q-btn flat
  17. padding="1px 23px"
  18. label="لغو"
  19. @click="emptyEditSelectorValue" />
  20. </div>
  21. <div>
  22. <q-btn unelevated
  23. class="filter-btn"
  24. color="positive"
  25. padding="1px 23px"
  26. label="اعمال"
  27. @click="editSelectedContents" />
  28. </div>
  29. </div>
  30. </div>
  31. <div v-else
  32. class="menu-mode flex items-center">
  33. <div class="header-item flex items-center">
  34. <entity-crud-form-builder v-model:value="setInput" />
  35. <q-btn color="positive"
  36. class="q-ml-sm"
  37. unelevated
  38. label="افزودن به مجموعه"
  39. @click="attachToSet" />
  40. </div>
  41. <div class="line header-item" />
  42. <div class="header-item selector">
  43. <q-select v-model="editSelectorValue"
  44. borderless
  45. label="ویرایش"
  46. :options="editSelectorOptions" />
  47. </div>
  48. <div class="header-item selector">
  49. <q-select v-model="moreSelectorValue"
  50. borderless
  51. label="بیشتر"
  52. :options="moreSelectorOptions"
  53. @update:model-value="executeMoreSelectorAction" /></div>
  54. </div>
  55. </q-card>
  56. <q-card v-if="isInEditMode"
  57. class="bg-secondary q-pa-md lower-card">
  58. <form-builder ref="formBuilder"
  59. v-model:value="allEditModeInputs[chosenInputIndex]" />
  60. </q-card>
  61. </div>
  62. </div>
  63. </template>
  64. <script>
  65. import FormBuilder from 'quasar-form-builder/src/FormBuilder.vue'
  66. import { APIGateway } from 'src/api/APIGateway'
  67. import { EntityCrudFormBuilder } from 'quasar-crud'
  68. import { shallowRef } from 'vue'
  69. import TagsComponent from 'components/Utils/Tags.vue'
  70. const Tags = shallowRef(TagsComponent)
  71. export default {
  72. name: 'EntityEditHeader',
  73. components: { FormBuilder, EntityCrudFormBuilder },
  74. props: {
  75. selectedValues: {
  76. default() {
  77. return []
  78. },
  79. type: Array
  80. }
  81. },
  82. emits: [
  83. 'selectedValues',
  84. 'contentUpdated'
  85. ],
  86. data() {
  87. return {
  88. moreSelectorValue: 'بیشتر',
  89. moreSelectorOptions: [
  90. { label: 'حذف', value: 'delete' }
  91. // { label: 'دانلود', value: 'download' }
  92. ],
  93. editSelectorValue: 'ویرایش',
  94. editSelectorOptions: [
  95. { label: 'عنوان', value: 'name-main' },
  96. { label: 'توضیحات', value: 'description-main' },
  97. { label: 'تگ ها', value: 'tags-main' },
  98. { label: 'وضعیت', value: 'status-main' }
  99. ],
  100. setInput: [
  101. {
  102. type: 'entity',
  103. responseKey: 'data.set',
  104. name: 'set',
  105. placeholder: 'مجموعه محتوا را انتخاب کنید',
  106. col: 'col-12',
  107. selectionMode: 'single',
  108. popUpButtonConfig: {
  109. unelevated: true,
  110. color: 'white',
  111. textColor: 'black',
  112. badgeColor: 'positive',
  113. label: 'انتخاب از لیست مجموعه ها'
  114. },
  115. dialogConfirmButtonConfig: {
  116. unelevated: true,
  117. color: 'positive',
  118. label: 'ثبت مجموعه'
  119. },
  120. indexConfig: {
  121. apiAddress: APIGateway.set.APIAdresses.base,
  122. tableTitle: 'مجموعه ها',
  123. tableKeys: {
  124. data: 'data',
  125. total: 'meta.total',
  126. currentPage: 'meta.current_page',
  127. perPage: 'meta.per_page',
  128. pageKey: 'contentsetPage'
  129. },
  130. table: {
  131. columns: [
  132. {
  133. name: 'id',
  134. required: true,
  135. label: '#',
  136. align: 'left',
  137. field: row => row.id
  138. },
  139. {
  140. name: 'title',
  141. required: true,
  142. label: 'عنوان',
  143. align: 'left',
  144. field: row => row.title
  145. }
  146. ],
  147. data: []
  148. },
  149. inputs: [
  150. { type: 'input', name: 'search', value: null, outlined: true, placeholder: 'انتخاب نمایید', label: 'جست و جو', col: 'col-md-3' }
  151. ],
  152. itemIdentifyKey: 'id'
  153. },
  154. itemIndicatorKey: 'title',
  155. value: [],
  156. selected: []
  157. }
  158. ],
  159. allEditModeInputs: [
  160. [
  161. {
  162. type: 'select',
  163. name: 'name-main',
  164. label: 'نوع ویرایش:',
  165. col: 'col-md-4',
  166. value: 'concatEnd',
  167. outlined: true,
  168. placeholder: 'انتخاب نمایید',
  169. options: [
  170. { label: 'افزودن به انتهای عنوان', value: 'concatEnd' },
  171. { label: 'افزودن به ابتدای عنوان', value: 'concatStart' },
  172. { label: 'حذف واژه از عنوان', value: 'delete' },
  173. { label: 'جاگزینی واژه در توضیحات', value: 'replace' }
  174. ]
  175. },
  176. {
  177. type: 'input',
  178. name: 'name',
  179. outlined: true,
  180. autogrow: true,
  181. value: null,
  182. placeholder: 'متن مورد نظر خود را وارد نمایید',
  183. label: 'متن ویرایش:',
  184. col: 'col-md-8',
  185. applyGridSystem: false
  186. },
  187. {
  188. // type: 'formBuilder',
  189. type: 'hidden',
  190. name: 'replace',
  191. col: 'col-md-8',
  192. value: [
  193. {
  194. type: 'input',
  195. name: 'name',
  196. outlined: true,
  197. autogrow: true,
  198. value: null,
  199. placeholder: 'واژه مورد نظر خود را وارد نمایید',
  200. label: 'واژه فعلی:',
  201. col: 'col-md-6'
  202. },
  203. {
  204. type: 'input',
  205. name: 'name',
  206. outlined: true,
  207. autogrow: true,
  208. value: null,
  209. placeholder: 'واژه مورد نظر خود را وارد نمایید',
  210. label: 'واژه جایگزین:',
  211. col: 'col-md-6'
  212. }
  213. ]
  214. }
  215. ],
  216. [
  217. {
  218. type: 'select',
  219. name: 'description-main',
  220. label: 'نوع ویرایش:',
  221. col: 'col-md-4',
  222. value: 'concatEnd',
  223. outlined: true,
  224. placeholder: 'انتخاب نمایید',
  225. options: [
  226. { label: 'افزودن به انتهای توضیحات', value: 'concatEnd' },
  227. { label: 'افزودن به ابتدای توضیحات', value: 'concatStart' },
  228. { label: 'حذف واژه از توضیحات', value: 'delete' },
  229. { label: 'جاگزینی واژه در توضیحات', value: 'replace' }
  230. ]
  231. },
  232. {
  233. type: 'input',
  234. name: 'description',
  235. outlined: true,
  236. autogrow: true,
  237. value: null,
  238. placeholder: 'متن مورد نظر خود را وارد نمایید',
  239. label: 'متن ویرایش:',
  240. col: 'col-md-8'
  241. },
  242. {
  243. // type: 'formBuilder',
  244. type: 'hidden',
  245. name: 'replace',
  246. col: 'col-md-8',
  247. value: [
  248. {
  249. type: 'input',
  250. name: 'description',
  251. outlined: true,
  252. autogrow: true,
  253. value: null,
  254. placeholder: 'واژه مورد نظر خود را وارد نمایید',
  255. label: 'واژه فعلی:',
  256. col: 'col-md-6'
  257. },
  258. {
  259. type: 'input',
  260. name: 'description',
  261. outlined: true,
  262. autogrow: true,
  263. value: null,
  264. placeholder: 'واژه مورد نظر خود را وارد نمایید',
  265. label: 'واژه جایگزین:',
  266. col: 'col-md-6'
  267. }
  268. ]
  269. }
  270. ],
  271. [
  272. {
  273. type: 'select',
  274. name: 'tags-main',
  275. outlined: true,
  276. placeholder: 'انتخاب نمایید',
  277. label: 'نوع ویرایش:',
  278. col: 'col-md-4',
  279. value: 'add',
  280. options: [
  281. { label: 'اضافه کردن تگ', value: 'add' },
  282. { label: 'حذف کردن تگ', value: 'delete' },
  283. { label: 'جابجایی تگ', value: 'replace' }
  284. ]
  285. },
  286. {
  287. type: Tags,
  288. name: 'description',
  289. label: 'متن مورد نظر خود را وارد نمایید',
  290. placeholder: ' ',
  291. outlined: true,
  292. responseKey: 'data.tags',
  293. col: 'col-md-8'
  294. },
  295. // {
  296. // type: 'input',
  297. // name: 'description',
  298. // outlined: true,
  299. // autogrow: true,
  300. // value: null,
  301. // placeholder: 'متن مورد نظر خود را وارد نمایید',
  302. // label: 'تگ ها:',
  303. // col: 'col-md-8'
  304. // },
  305. {
  306. // type: 'formBuilder',
  307. type: 'hidden',
  308. name: 'replace',
  309. col: 'col-md-8',
  310. hidden: true,
  311. value: [
  312. {
  313. type: 'input',
  314. name: 'description',
  315. outlined: true,
  316. autogrow: true,
  317. value: null,
  318. placeholder: 'متن مورد نظر خود را وارد نمایید',
  319. label: 'تگ فعلی:',
  320. col: 'col-md-6'
  321. },
  322. {
  323. type: 'input',
  324. name: 'description',
  325. outlined: true,
  326. autogrow: true,
  327. value: null,
  328. placeholder: 'متن مورد نظر خود را وارد نمایید',
  329. label: 'تگ جایگزین:',
  330. col: 'col-md-6'
  331. }
  332. ]
  333. }
  334. ],
  335. [
  336. {
  337. type: 'select',
  338. name: 'status-main',
  339. outlined: true,
  340. placeholder: ' ',
  341. label: 'وضعیت:',
  342. col: 'col-md-4',
  343. value: null,
  344. options: [
  345. // { label: 'پیش نویس', value: 5 },
  346. // { label: 'زمان بندی شده', value: 3 },
  347. // { label: 'منتشر شده', value: 8 },
  348. { label: 'غیرفعال', value: 0 },
  349. { label: 'فعال', value: 1 }
  350. ]
  351. }
  352. ]
  353. ],
  354. chosenInputIndex: 0
  355. }
  356. },
  357. computed: {
  358. isInEditMode() {
  359. return this.editSelectorValue && this.editSelectorValue !== 'ویرایش'
  360. }
  361. },
  362. watch: {
  363. editSelectorValue(inputObj) {
  364. if (!this.isInEditMode) {
  365. return
  366. }
  367. this.chooseFormBuilderInputs(inputObj.value)
  368. },
  369. allEditModeInputs: {
  370. handler(newValue) {
  371. this.setChosenInputForm(newValue)
  372. },
  373. deep: true
  374. }
  375. },
  376. methods: {
  377. editSelectedContents () {
  378. const currentInput = this.allEditModeInputs[this.chosenInputIndex]
  379. const requestBody = this.getEditContentRequestBody(currentInput[0].value, currentInput)
  380. if (!currentInput || !currentInput[0].name) {
  381. return
  382. }
  383. const currentInputName = currentInput[0].name
  384. const apiInstance = this.$apiGateway.content
  385. if (currentInputName === 'tags-main') {
  386. apiInstance.bulkEditTags(requestBody)
  387. .then((res) => {
  388. this.$q.notify({
  389. type: 'positive',
  390. message: res.message,
  391. position: 'top'
  392. })
  393. this.contentUpdated()
  394. })
  395. .catch(() => {})
  396. } else if (currentInputName === 'status-main') {
  397. apiInstance.bulkUpdate(requestBody)
  398. .then((res) => {
  399. this.$q.notify({
  400. type: 'positive',
  401. message: res.message,
  402. position: 'top'
  403. })
  404. this.contentUpdated()
  405. })
  406. .catch(() => {})
  407. } else {
  408. apiInstance.bulkEditText(requestBody)
  409. .then((res) => {
  410. this.$q.notify({
  411. type: 'positive',
  412. message: res.message,
  413. position: 'top'
  414. })
  415. this.contentUpdated()
  416. })
  417. .catch(() => {})
  418. }
  419. },
  420. contentUpdated () {
  421. this.$emit('contentUpdated')
  422. },
  423. getEditContentRequestBody (mode, currentInput) {
  424. const currentInputName = currentInput[0].name
  425. return {
  426. content_ids: this.getSelectedValuesIds(),
  427. ...((currentInputName.includes('name') ||
  428. currentInputName.includes('description')) &&
  429. { column: currentInputName.replace('-main', '') }),
  430. ...(((currentInputName !== 'status-main')) &&
  431. { operation: currentInput[0].value }),
  432. ...((currentInputName.includes('name') ||
  433. currentInputName.includes('description')) &&
  434. { text: currentInput[0].value === 'replace' ? currentInput[2].value[0].value : currentInput[1].value }),
  435. ...((!currentInputName.includes('tags') && currentInput[0].value === 'replace') &&
  436. { replacing_text: currentInput[2].value[1].value }),
  437. ...((currentInputName.includes('tags') && currentInput[0].value === 'replace') &&
  438. { tag: currentInput[2].value[0].value }),
  439. ...((currentInputName.includes('tags') && currentInput[0].value !== 'replace') &&
  440. { tags: currentInput[1].value }),
  441. ...((currentInputName.includes('tags') && currentInput[0].value === 'replace') &&
  442. { replacing_tag: currentInput[2].value[1].value }),
  443. ...(((currentInputName === 'status-main')) &&
  444. { enable: currentInput[0].value })
  445. // validSince: '2022-09-03 12:41:55'
  446. }
  447. },
  448. deleteSelectedContents () {
  449. this.$apiGateway.content.deleteContents({
  450. contents: this.getSelectedValuesIds()
  451. })
  452. .then((res) => {
  453. this.$q.notify({
  454. type: 'positive',
  455. message: res.message,
  456. position: 'top'
  457. })
  458. this.contentUpdated()
  459. })
  460. .catch(() => {})
  461. this.moreSelectorValue = 'بیشتر'
  462. },
  463. attachToSet() {
  464. const setId = this.setInput[0].selected.id
  465. this.$apiGateway.set.attachContents(setId, {
  466. contents: this.getSelectedValuesIds()
  467. })
  468. .then((res) => {
  469. this.$q.notify({
  470. type: 'positive',
  471. message: res.message,
  472. position: 'top'
  473. })
  474. this.setInput[0].value = []
  475. this.setInput[0].selected = []
  476. })
  477. .catch(() => {})
  478. },
  479. getSelectedValuesIds() {
  480. return this.selectedValues.map(item => item.id)
  481. },
  482. executeMoreSelectorAction (selectedAction) {
  483. if (selectedAction.value === 'delete') {
  484. this.deleteSelectedContents()
  485. }
  486. },
  487. emptyEditSelectorValue() {
  488. this.editSelectorValue = 'ویرایش'
  489. this.$refs.formBuilder.clearFormBuilderInputValues()
  490. },
  491. chooseFormBuilderInputs (chosenInputName) {
  492. this.chosenInputIndex = this.allEditModeInputs.findIndex(input => input[0].name === chosenInputName)
  493. },
  494. setChosenInputForm (value) {
  495. const chosenInput = value[this.chosenInputIndex]
  496. if (!chosenInput[2]) {
  497. return
  498. }
  499. if (chosenInput[0].value === chosenInput[2].name) {
  500. this.setFormBuilderReplaceMode(chosenInput)
  501. } else {
  502. this.setFormBuilderInputMode(chosenInput)
  503. }
  504. },
  505. setFormBuilderReplaceMode (chosenInput) {
  506. chosenInput[1].type = 'hidden'
  507. chosenInput[2].type = 'formBuilder'
  508. },
  509. setFormBuilderInputMode (chosenInput) {
  510. chosenInput[1].type = 'input'
  511. chosenInput[2].type = 'hidden'
  512. }
  513. }
  514. }
  515. </script>
  516. <style scoped lang="scss">
  517. .entity-edit-header {
  518. padding-top: 20px;
  519. .upper-card {
  520. color: var(--alaa-Neutral2);
  521. display: grid;
  522. grid-template-columns: 170px auto;
  523. :deep(.q-field) {
  524. .q-field__append {
  525. color: var(--alaa-Neutral2);
  526. }
  527. .q-field__native {
  528. color: var(--alaa-Neutral2);
  529. }
  530. }
  531. .header-item {
  532. margin-left: 10px;
  533. margin-right: 10px;
  534. }
  535. .line {
  536. //padding-bottom: 20px;
  537. //padding-right: 0;
  538. width: 0;
  539. height: 42px;
  540. border: 1px solid #ffe9cc;
  541. }
  542. .base-part {}
  543. .edit-mode {
  544. .selector {
  545. width: 120px;
  546. }
  547. .lower-card{
  548. //color: var(--alaa-TextSecondary);
  549. }
  550. }
  551. }
  552. }
  553. </style>